当前位置:首页 » 《随便一记》 » 正文

【控制台五子棋游戏】这学期的编程大作业有救了!(建议收藏)_Wyf_Fj的博客

2 人参与  2022年02月25日 13:42  分类 : 《随便一记》  评论

点击全文阅读


五子棋游戏

  • 1、Chess.h 头文件
  • 2、Chess.c源文件
  • 3、game.c测试文件

本篇博客提供一份五子棋游戏的代码,也不多,三百多行,比较适合想要练习的新手以及应付作业的童鞋!
由于现在是期初,大家记得收藏码住哦!!!

在这里插入图片描述

1、Chess.h 头文件

首先,Chess.h头文件中进行相关函数的声明:

#pragma once
#include <stdio.h>
#include <stdbool.h>
#include <Windows.h>
#define ROW        15    //棋盘行数
#define COL        15    //棋盘列数
#define WINNUM    5     //赢棋标准
enum//菜单项
{
	Over,
	PvP,
};

void Menu();//打印菜单
void GamePVP();
void InitBoard(int board[ROW][COL], int row, int col);//初始化棋盘
void PrintBoard(int board[ROW][COL], int row, int col);//打印棋盘
bool GameOver(int board[ROW][COL], int row, int col);//判断输赢
bool CheckRow(int board[ROW][COL], int row, int col, int winnum);//判断行是否有五个连续
bool CheckCol(int board[ROW][COL], int row, int col, int winnum);//判断列是否有五个连续
bool CheckLSlash(int board[ROW][COL], int row, int col, int winnum);//判断'\'方向是否有五个连续
bool CheckRSlash(int board[ROW][COL], int row, int col, int winnum);//判断'/'方向是否有五个连续
int ChessRetract(int board[ROW][COL], int x1, int y1, int x2, int y2,int* ChessNum,int* Retract);//悔棋

2、Chess.c源文件

Chess.c文件中进行相关函数的实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include "Chess.h"
void Menu()
	{
	printf(" ------------------------------------- \n");
	printf("|<<<<<<<<<<<<<<<<五子棋>>>>>>>>>>>>>>>|\n");
	printf("|<<<<<<<<<<<< 选择对战模式 >>>>>>>>>>>|\n");
	printf("|<<<<<<<<<<<<    1.PvP    >>>>>>>>>>>|\n");
	printf("|<<<<<<<<<<<<  0.退出游戏  >>>>>>>>>>>|\n");
	printf("|<<<<<<<<<<<< 当前版本:1.0 >>>>>>>>>>>|\n");
	printf(" ------------------------------------- \n");
}
void InitBoard(int board[ROW][COL],int row,int col)
{	
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			board[i][j] = ' ';
		}
	}
}
void PrintBoard(int board[ROW][COL],int row,int col)
{
	int i, j;
	for (i = 0; i < col; i++)
	{
		if (i == 0)
		{
			printf(" ");
		}
	    printf(" %2d ", i+1);
	}
	putchar('\n');
	for (i = 0; i < row; i++)
	{
		printf("%-2d", i + 1);
		for (j = 0; j < col; j++)
		{
			printf(" %c ", board[i][j]);
			if (j != col - 1)
			{
				putchar('|');
			}
		}
		putchar('\n');
		if (i != row - 1)
		{
			for (j = 0; j < col; j++)
			{
				if (j == 0)
				{
					printf("  ");
				}
				printf("---");
				if (j != col - 1)
				{
					putchar('|');
				}
			}
		}
		putchar('\n');
	}
}
bool GameOver(int board[ROW][COL], int row, int col)
{
	if (CheckRow(board, row, col, WINNUM))
	{
		return true;
	}
	if (CheckCol(board, row, col, WINNUM))
	{
		return true;
	}
	if (CheckLSlash(board, row, col, WINNUM))
	{
		return true;
	}
	if (CheckRSlash(board, row, col, WINNUM))
	{
		return true;
	}
	return false;
}
int ChessRetract(int board[ROW][COL], int x1, int y1, int x2, int y2, int* ChessNum, int* Retract)
{//x1y1是当前落子方上一次的坐标,x2y2是另一方上一次的坐标
	if ((*ChessNum)>=2)
	{
		if (*Retract > 0)//还有悔棋次数的情况
		{
			board[x1-1][y1-1] = board[x2-1][y2-1] = ' ';
			*ChessNum -= 2;//总落棋数减2
			(*Retract)--;//剩余悔棋数减1
			return 1;
		}
		else//没有悔棋次数
		{
			return 0;
		}
	}
	else
	{
		return -1;//棋盘上的落子数不支持悔棋
	}
}
bool CheckRow(int board[ROW][COL], int row, int col, int winnum)
{
	int i,j,k;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j <= col - winnum; j++)//只需判断1~11【数组0~10】列往后是否有WIN_NUM个连续
		{
			int flag = 1;
			for (k = 0; k < winnum; k++)//判断是否有连续的WIN_NUM个
			{
				if (board[i][j] != board[i][j + k])
				{
					flag = 0;
				}
			}
			if (flag == 1 && board[i][j]!=' ')//有五个 非空格(即棋子) 连续
			{
				return true;
			}
		}
	}
	return false;
}
bool CheckCol(int board[ROW][COL], int row, int col, int winnum)
{
	int i, j, k;
	for (i = 0; i <= row - winnum; i++)//只需判断1~11【数组0~10】行往下是否有WIN_NUM个连续
	{
		for (j = 0; j < col; j++)
		{
			int flag = 1;
			for (k = 0; k < winnum; k++)//判断是否有连续的WIN_NUM个
			{
				if (board[i][j] != board[i + k][j])
				{
					flag = 0;
				}
			}
			if (flag == 1 && board[i][j] != ' ')//有五个 非空格(即棋子) 连续
			{
				return true;
			}
		}
	}
	return false;
}
bool CheckLSlash(int board[ROW][COL], int row, int col, int winnum)
{
	int i, j, k;
	for (i = winnum - 1; i < row; i++)
	{
		for (j = 0; j < col - winnum; j++)
		{
			int flag = 1;
			for (k = 0; k < winnum; k++)
			{
				if (board[i][j] == ' ' || board[i][j] != board[i - k][j + k])
				{
					flag = 0;
					break;
				}
			}
			if (flag)
			{
				return true;
			}
		}
	}
	return false;
}
bool CheckRSlash(int board[ROW][COL], int row, int col, int winnum)
{
	int i, j, k;
	for (i = 0; i < row - winnum; i++)
	{
		for (j = 0; j < col - winnum; j++)
		{
			int flag = 1;
			for (k = 0; k < winnum; k++)
			{
				if (board[i][j] == ' ' || board[i][j] != board[i + k][j + k])
				{
					flag = 0;
					break;
				}
			}
			if (flag)
			{
				return true;
			}
		}
	}
	return false;
}
void GamePVP()
{
	int board[ROW][COL];
	int WhiteRetract = 2;        //白棋剩余悔棋次数
	int BlackRetract = 2;        //黑棋剩余悔棋次数
	int	ChessNum = 0;            //已下的棋子总数
	InitBoard(board, ROW, COL);
	int x=0, y=0;//保存当前落子坐标
	int x_w=0, x_b=0, y_w=0, y_b=0;//保存上一次的落子坐标
	//游戏部分
	while (1)
	{
		//白方落子
		while (1)
		{
			PrintBoard(board, ROW, COL);//打印棋盘
			printf("请白方'*'输入落子坐标(数字+空格+数字<输入0 0可悔棋>)->");
			//清空输入缓冲区
			char clear;
			while ((clear = getchar()) != '\n')
			{
				;
			}
			scanf("%d%d", &x, &y);//读取白子坐标
			if (x == 0 && y == 0)//悔棋
			{
				int ret = ChessRetract(board, x_w, y_w, x_b, y_b, &ChessNum,&WhiteRetract);
				if (ret == -1)
				{
					printf("当前无法悔棋!\n");
				}
				else
				{
					printf("白方还剩%d次悔棋机会\n", WhiteRetract);
					ChessNum -= 2;
				}
			}
			else
			{
				x_w = x;
				y_w = y;
				if (!(x_w >= 1 && x_w <= 15 && y_w >= 1 && y_w <= 15))//非法坐标
				{
					printf("\n\n\t坐标不合法!(1≤x,y≤15)\n");
				}
				else if (board[x_w - 1][y_w - 1] != ' ')
				{
					printf("\n\n\t此处已有棋子,请选择空白处落子!\n");
				}
				else
				{
					board[x_w - 1][y_w - 1] = '*';
					ChessNum++;
					break;
				}
			}
		}
		//平局情况
		if (ChessNum == ROW * COL)
		{
			printf("平局!\n");
			break;
		}
		PrintBoard(board, ROW, COL);//打印棋盘
		//白方下完后游戏结束,即白方胜的情况
		if (GameOver(board, ROW, COL))
		{
			printf("白方'*'胜!\n");
			break;
		}
		system("cls");
		//黑方落子
		while (1)
		{
			PrintBoard(board, ROW, COL);//打印棋盘
			printf("请黑方'#'输入落子坐标(数字+空格+数字<输入0 0可悔棋>)->");
			//清空输入缓冲区
			char clear;
			while ((clear = getchar()) != '\n')
			{
				;
			}
			scanf("%d%d", &x, &y);//读取坐标
			if (x == 0 && y == 0)//悔棋
			{
				int ret = ChessRetract(board, x_b, y_b, x_w, y_w, &ChessNum, &BlackRetract);
				if (ret == -1)
				{
					printf("当前无法悔棋!\n");
				}
				else
				{
					printf("黑方还剩%d次悔棋机会\n", BlackRetract);
					ChessNum -= 2;
				}
			}
			else
			{
				x_b = x;
				y_b = y;
				if (!(x_b >= 1 && x_b <= 15 && y_b >= 1 && y_b <= 15))//非法坐标
				{
					printf("\n\n\t坐标不合法!(1≤x,y≤15)\n");
				}
				else if (board[x_b - 1][y_b - 1] != ' ')
				{
					printf("\n\n\t此处已有棋子,请选择空白处落子!\n");
				}
				else
				{
					board[x_b - 1][y_b - 1] = '#';
					ChessNum++;
					break;
				}
			}
		}
		PrintBoard(board, ROW, COL);//打印棋盘
		//白方下完后游戏结束,即白方胜的情况
		if (GameOver(board, ROW, COL))
		{
			printf("黑方'#'胜!\n");
			break;
		}
		system("cls");
	}
}

3、game.c测试文件

在game.c中进行主函数的编写和测试

#define _CRT_SECURE_NO_WARNINGS 1
#include "Chess.h"
int main()
{
	int choice;
	do {
		Menu();
		printf("请选择>>");
		scanf("%d", &choice);
		switch (choice)
		{
		default:	
			system("cls");
			printf("请输入菜单中已有选项!\n");
			break;
		case PvP:
			system("cls");
			GamePVP();
			break;
		case Over:
			printf("游戏结束|BYE BYE!");
			break;
		}
	} while (choice);
	return 0;
}

源代码已经上传至我的码云上,大家可以点击链接自行下载——
五子棋源代码

//铁子们,如果这篇博客对你有所帮助,留下你们的三连吧!!!!


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/35350.html

悔棋  落子  坐标  
<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1