三字棋的实现要分成三个大模块
一个是主函数的创建---------test.c
一个是游戏函数的实现------game.c
最后是包含的头文件---------game.h
确定游戏逻辑
1、进入主函数,需要打印菜单来供用户选择模式
选择1为开始游戏,选择0为退出游戏
2、选择1进入游戏后,开始实现游戏运行
3、游戏运行需要棋盘,下棋,判断输赢
棋盘本质为二维数组,用来存储数据,即用户和电脑下的棋子
打印棋盘,每走一步显示棋盘内容。
下棋,输入数组坐标,将棋子放入棋盘中,如果为空,下棋成功,否则下棋失败
判断输赢,看棋盘上是否有三个一样的棋子连成一条线,若是,则显示输赢。
下面进行细化分析:
主函数:
//创建主函数
int main()
{
//进入主逻辑函数
test();
return 0;
}
主函数创建完成后调用主逻辑函数,主逻辑函数包含三个逻辑:
1、选择 1 玩游戏
2、选择 0 退出游戏
3、输入错误输入的不是1也不是0的情况
主逻辑函数采用do while 语句来实现,由于我们在下完一盘棋后还可以继续下或者选择退出游戏,因此需要循环来实现,并且,只要游戏运行起来,就要循环一次,所以采用do while
创建 input 来接收输入数值,并且用input来控制switch来选择模式。
do while 的控制也是使用input 。由于input=1为玩游戏模式,while(input)条件成立,在玩完一次游戏后,将继续执行循环体。而input为0的时候switch为退出游戏,while(input)条件为0,循环体不执行。当输入input为其他值的时候,while循环总会执行,来到选择模式界面,直到输入1或者0。
//主逻辑函数
void test()
{
//进入游戏界面后根据选择数字来进行游戏模式
int input = 0;
srand((unsigned int)time(NULL));
//运用switch语句进行选择
//整体是一个循环
do//do while循环可以上来先执行一次
{
//菜单打印
menu();//主界面
scanf("%d", &input);
switch (input)
{
case 1:
//实现函数游戏
game();
break;
case 0:
//退出游戏
printf("退出游戏\n");
break;
default:
//选择错误
printf("选择错误,重新选择\n");
}
} while (input);
}
内部包含一个目录函数,目录函数为用printf打印出的简易界面
void menu()
{
printf("************************\n");
printf("******* 1.play ********\n");
printf("******* 0.exit ********\n");
printf("************************\n");
}
要想玩游戏,首先需要棋盘,然后才能下棋。
棋盘我们用二维数组来储存,为了方便以后将棋盘放大,或者更改为五子棋,采用define定义棋盘的长和宽,方便以后更改。
//字符定义
//棋盘的长宽
#define COL 3
#define ROW 3
棋盘创建完毕后,需要对棋盘进行初始化。
因此我们需要初始化棋盘函数。
不仅如此,我们还需要打印出期盘,让棋盘展现给玩家,方便玩家下棋或者观看局势。
只有棋盘不行,核心是下棋,因此我们还需要下棋函数来实现。
因此,主游戏函数分为4个方面
1、棋盘创建
2、棋盘初始化
3、打印棋盘
4、下棋
//主游戏函数
void game()
{
//1.创建棋盘,本质为二维数组
char board[ROW][COL] = { 0 };
//2.对棋盘进行初始化
InitBoard(board, ROW, COL);
//3.打印棋盘
DisplayBoard(board, ROW, COL);
//4.下棋
//分为,玩家下棋和电脑下棋
//还要判断输赢
PlayChess(board,ROW,COL);
}
初始化棋盘就是将棋盘内部全部置为空格
//将棋盘内部全部初始化为棋盘空格
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0;i < row;i++)
{
int j = 0;
for (j = 0;j < col;j++)
{
board[i][j] = ' ';
}
}
}
棋盘的打印函数本质上还是在打印二维数组。但是棋子之间需要分隔符号隔开,每一行之间也需要分开。
棋盘实现后:
我们将棋盘分开实现
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0;i < row;i++)//打印每一行的棋盘
{
int j = 0;
for (j = 0;j < col;j++)//打印每一列
{
printf(" %c ", board[i][j]);
if (j < col - 1)//列分隔符比列数少一列
{
printf("|");
}
}
printf("\n");//换行,开始打印行与行之间的分隔符
if (i < row - 1)//行分隔符比行数少一行
{
for (j = 0;j < col;j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");//打印完每一行后换行
}
}
}
棋盘打印完后开始下棋,下棋我们分为两种模式,即玩家先手和电脑先手。
两种模式可供玩家选择,只需要用switch语句来实现
模式选择的循环采用goto语句进行实现的,因为无论选择哪一方先走,都是在游戏结束后才停下,并且返回到主界面,而不是选择模式界面,因此在输入1,2,0之外的数字时只需要用goto语句再一次的跳到选择模式界面就可以。
//下棋函数
void PlayChess(char board[ROW][COL],int row,int col)
{
int flag = 0;
char ret = 0;
//选择游戏模式,玩家先走和电脑先走
flag:
printf("*********************\n");
printf("**** 1. 玩家先走 ****\n");
printf("**** 2. 电脑先走 ****\n");
printf("**** 0. 返回 ****\n");
printf("*********************\n");
int input = 0;
scanf("%d", &input);
switch (input)
{
case 1:
while (1)
{
//玩家下棋
player_move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
ret=IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋
computer_move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家获胜\n");
}
else if (ret == '#')
{
printf("电脑获胜\n");
}
else
{
printf("平局\n");
}
DisplayBoard(board, ROW, COL);
break;
case 2:
while (1)
{
//电脑下棋
computer_move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
//玩家下棋
player_move(board, ROW, COL);
DisplayBoard(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家获胜\n");
}
else if (ret == '#')
{
printf("电脑获胜\n");
}
else
{
printf("平局\n");
}
DisplayBoard(board, ROW, COL);
break;
case 0:
//返回主界面
break;
default:
printf("输入错误,重新输入\n");
goto flag;//返回到选择模式界面
}
}
至于两种模式,无非是玩家下棋和电脑下棋执行顺序的问题,并没有什么其他不同点。
因此,我们只介绍一种模式。
在选择1进入玩家先走后,下棋是一个循环过程,直到平局或者一方获胜才停止。
因此最重要的是三个函数的实现。
玩家棋子为" * "
玩家下棋,就是将棋子下到创建好的数组里面,接收玩家的坐标,然后将其作为数组元素下标,找到元素,更改为棋子即可。
每次下棋之后需要判断此坐标是否被占用,如果被占用证明坐标不合法,需要重新输入。
只要输入正确的坐标,则跳出循环,执行下一步。
void player_move(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋\n");
while(1)
{
printf("请输入坐标:>\n");
scanf("%d %d", &x, &y);
printf("玩家走:\n");
if (x > 0 && x <= 3 && y > 0 && y <= 3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标被占用,重新输入\n");
}
}
else
{
printf("坐标非法\n");
}
}
至于代码中数组的坐标为何是输入坐标减去一,是因为玩家输入的1行1列的坐标实际上在数组中储存的下标为[0][0]
所以需要减一
电脑棋子为" # "
电脑下棋需要随机产生下标,随机数的产生只需要在主函数中调用一次即可。
对电脑生成的随机坐标也需要进行判断,看是否为空坐标。只有空坐标才能放入棋子。
下棋成功后跳出循环
//电脑下棋
void computer_move(char board[ROW][COL], int row, int col)
{
printf("电脑走:\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % 3;//产生随机坐标,%3产生0~2的数
y = rand() % 3;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
在每一次下棋结束后,都需要对棋盘进行判断。
判断情况有4种:
1.玩家获胜
2.电脑获胜
3.平局----棋盘满了
4.不满足前三种,游戏继续
因此在设计判断输赢的函数的时候只需要创建一个函数返回4中状态即可
我们设定:
返回" * "为玩家获胜
返回" # "为电脑获胜
返回"Q"为平局
返回"C"为游戏继续
获胜的条件为行或者列或者对角线有三个元素连成一条线则为获胜
//判断输赢
char IsWin(char board[ROW][COL], int row, int col)
{
//判断行
int i = 0;
for (i = 0;i < row;i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ')
{
return board[i][0];
}
}
//判断列
for (i = 0;i < col;i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
{
return board[1][i];
}
}
//判断对角线
if(board[0][0]==board[1][1]&&board[1][1]==board[2][2]&&board[1][1]!=' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判断平局---棋盘满了,未分出胜负
//运用一个函数进行判断,棋盘满了返回1则为平局
if (IsFull(board, ROW, COL) == 1)
{
return 'Q';
}
//上述条件均不满足,游戏继续
return 'C';
}
在这里引用了一个新函数来判断棋盘是否满,由于此函数是输赢函数的附属函数,所以设计为静态函数,只在此处可以调用
//判断棋盘是否满了
static int IsFull(char board[ROW][COL], int row, int col)//此函数为判断输赢的附属函数,仅在此处使用
{
int i = 0;
for (i = 0;i < row;i++)
{
int j = 0;
for(j=0;j
因此在下棋函数中无论玩家还是电脑,每走完一步都对其进行判断,若返回的是"C"则不会进入if语句,不会跳出下棋的循环,玩家继续下棋。
若返回的不是"C"则证明产生了其他三种情况,进入if语句跳出循环,判断哪方输赢,或者平局。
//头文件
#include
#include
#include
//字符定义
//棋盘的长宽
#define COL 3
#define ROW 3
//函数声明
//1.初始化棋盘
void InitBoard(char board[ROW][COL], int row,int col);
//2.打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//3.玩家下棋
void player_move(char board[ROW][COL], int row, int col);
//4.电脑下棋
void computer_move(char board[ROW][COL], int row, int col);
//5.判断输赢
char IsWin(char board[ROW][COL], int row, int col);
//头文件引用
#include
#include
#include
//定义变量
#define ROW 10
#define COL 10
#define chess 5
//函数声明
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayMove(char board[ROW][COL], int row, int col,int*x,int*y);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col,int*x,int*y);
//
//1. 玩家赢了 - *
//2. 电脑赢了 - #
//3. 平局 - Q
//4. 游戏继续 - C
//判断游戏是否有输赢
char IsWin(char board[ROW][COL], int row, int col);
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0;i < row;i++)
{
for (j = 0;j < col;j++)
{
board[i][j] = ' ';
}
}
}
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
//打印列标
for (i = 1;i < row+1;i++)
{
if (i > 9)
printf(" %d ",i);
else
printf(" %d ", i);
}
printf("\n");
for (i = 0;i < row; i++)
{
int j = 0;
for (j = 0;j < col;j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf(" %d", i+1);//打印行标
printf("\n");
if (i < row - 1)
{
int j = 0;
for (j = 0;j < col;j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
printf("\n");
}
}
}
//玩家下棋
void PlayMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("\n");
printf("玩家走:>\n");
printf("\n");
while (1)
{
int tem = getchar();//将缓存区的字符全部拿走
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)//判断坐标是否合法
{
//坐标是否被占用
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标被占用,请重新输入坐标");
}
}
else
{
printf("坐标不合法\n");
}
}
}
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("\n");
printf("电脑走:>\n");
printf("\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//
// 新版走法
void PlayMove(char board[ROW][COL], int row, int col, int* x, int *y)
{
while (1)
{
if (*x >= 1 && *x <= row && *y >= 1 && *y <= col)//判断坐标是否合法
{
//坐标是否被占用
if (board[*x - 1][*y - 1] == ' ')
{
board[*x - 1][*y - 1] = '*';
break;
}
else
{
int a = 0;
int b = 0;
printf("坐标被占用,请重新输入坐标\n");
scanf("%d %d",&a,&b);
*x = a;
*y = b;
}
}
else
{
int a = 0;
int b = 0;
printf("坐标不合法\n");
scanf("%d %d", &a, &b);
*x = a;
*y = b;
}
}
}
void ComputerMove(char board[ROW][COL], int row, int col,int *x,int *y)
{
printf("\n");
printf("电脑走:>\n");
printf("\n");
while (1)
{
int n = rand() % row;
int m = rand() % col;
int i = *x-1;
int j = *y-1;
if (board[i][j]==board[i-1][j]&&board[i][j]==board[i-2][j] && board[i][j] != ' ')
{
if (board[i + 1][j] == ' ')
{
board[i + 1][j] = '#';
break;
}
else goto Sui;
}
else if (board[i][j] == board[i + 1][j] && board[i][j] == board[i + 2][j] && board[i][j] != ' ')
{
if (board[i - 1][j] == ' ')
{
board[i - 1][j] = '#';
break;
}
else goto Sui;
}
else if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')
{
if (board[i][j - 1] == ' ')
{
board[i][j - 1] = '#';
break;
}
else goto Sui;
}
else if (board[i][j] == board[i][j -1] && board[i][j] == board[i][j - 2] && board[i][j] != ' ')
{
if (board[i][j + 1] == ' ')
{
board[i][j + 1] = '#';
break;
}
else goto Sui;
}
else if (board[i][j] == board[i - 1][j - 1] && board[i][j] == board[i -2][j -2] && board[i][j] != ' ')
{
if (board[i+1][j + 1] == ' ')
{
board[i + 1][j + 1] = '#';
break;
}
else goto Sui;
}
else if (board[i][j] == board[i +1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
{
if (board[i - 1][j -1] == ' ')
{
board[i - 1][j - 1] = '#';
break;
}
else goto Sui;
}
else if (board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] != ' ')
{
if (board[i+1][j - 1] == ' ')
{
board[i + 1][j - 1] = '#';
break;
}
else goto Sui;
}
else if (board[i][j] == board[i +1][j -1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ')
{
if (board[i-1][j + 1] == ' ')
{
board[i - 1][j + 1] = '#';
break;
}
else goto Sui;
}
else if (board[i][j] == board[i + 1][j] && board[i][j] == board[i-1][j] && board[i][j] != ' ')
{
if (board[i+2][j] == ' ')
{
if (board[i - 2][j] == ' ')
{
board[i + 2][j] = '#';
break;
}
}
else goto Sui;
}
else if (board[i][j] == board[i][j-1] && board[i][j] == board[i][j+1] && board[i][j] != ' ')
{
if (board[i][j+2] == ' ')
{
if (board[i][j-2] == ' ')
{
board[i][j+2] = '#';
break;
}
}
else goto Sui;
}
else if (board[i][j] == board[i-1][j - 1] && board[i][j] == board[i+1][j + 1] && board[i][j] != ' ')
{
if (board[i+2][j + 2] == ' ')
{
if (board[i-2][j - 2] == ' ')
{
board[i+2][j + 2] = '#';
break;
}
}
else goto Sui;
}
else if (board[i][j] == board[i +1][j - 1] && board[i][j] == board[i - 1][j + 1] && board[i][j] != ' ')
{
if (board[i + 2][j -2] == ' ')
{
if (board[i - 2][j + 2] == ' ')
{
board[i + 2][j - 2] = '#';
break;
}
}
else goto Sui;
}
else
{
Sui:
if (board[n][m] == ' ')
{
board[n][m] = '#';
break;
}
}
}
}
//判断是否棋盘已经满了
int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0;i < row;i++)
{
for (j = 0;j < col;j++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}
//判断输赢
// char IsWin(char board[ROW][COL], int row, int col)
//{
// int i = 0;
// //判断行
// for (i = 0;i < row;i++)
// {
// if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
// {
// return board[i][0];
// }
// }
// //判断三列
// for (i = 0;i < row;i++)
// {
// if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
// {
// return board[i][0];
// }
// }
// //判断对角线
// if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
// {
// return board[0][0];
// }
// if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
// {
// return board[0][0];
// }
//
//判断平局
//如果棋盘满了返回1,不满返回0
// int ret = IsFull(board, ROW, COL);
// if (ret == 1)
// {
// return 'Q';
// }
// return 'C';
//}
//判断输赢
char IsWin(char board[ROW][COL], int row, int col)
{
//判断行
int i = 0;
while (i 0)
{
if (board[i][j] == board[i + 1][j - 1] && board[i + 1][j - 1] == board[i + 2][j - 2] && board[i + 2][j - 2] == board[i + 3][j - 3] && board[i + 3][j - 3] == board[i + 4][j - 4] && board[i][j] != ' ')
{
return board[i][j];
}
}
else
{
break;
}
}
}
else
break;
}
int ret = IsFull(board, ROW, COL);
if (ret == 1)
{
return 'Q';
}
return 'C';
}
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//菜单函数
void menu()
{
printf("******************************\n");
printf("***** 简易版五子棋小游戏 *****\n");
printf("******** 1.开始 ********\n");
printf("******** 0.退出 ********\n");
printf("******************************\n");
}
void game()
{
//储存数据-二维数组
char board[ROW][COL];
//初始化棋盘-空格
InitBoard(board, ROW, COL);
//打印棋盘,本质是打印棋盘内容 //棋盘标号打印
DisplayBoard(board, ROW, COL);
//开始玩游戏
//选择谁先玩游戏
char ret = 0;
flag:
printf("\n");
printf("请选择(1.玩家先走 2.电脑先走)\n");
int n = 0;
scanf("%d", &n);
switch (n)
{
case 1:
{
while (1)
{
//玩家下棋
printf("\n");
printf("玩家走:>\n");
printf("\n");
int x = 0;
int y = 0;
scanf("%d %d",&x,&y);
PlayMove(board, ROW, COL,&x,&y);
int tem = getchar();
while (tem != '\n')
{
;
}
DisplayBoard(board, ROW, COL);
//判断玩家是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
//电脑下棋
ComputerMove(board, ROW, COL,&x,&y);
DisplayBoard(board, ROW, COL);
//判断电脑是否赢得游戏
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{
printf("\n");
printf("恭喜你,获胜了\n");
printf("\n");
}
if (ret == '#')
{
printf("\n");
printf("很遗憾,你输了\n");
printf("\n");
}
if (ret == 'Q')
{
printf("\n");
printf("旗鼓相当,平局\n");
printf("\n");
}
DisplayBoard(board, ROW, COL);
}
break;
case 2:
{
while (1)
{
int x = 0;
int y = 0;
//电脑下棋
ComputerMove(board, ROW, COL, &x, &y);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
//玩家下棋
printf("\n");
printf("玩家走:>\n");
printf("\n");
scanf("%d %d", &x, &y);
PlayMove(board, ROW, COL, &x, &y);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
{
printf("\n");
printf("恭喜你,获胜了\n");
printf("\n");
}
if (ret == '#')
{
printf("\n");
printf("很遗憾,你输了\n");
printf("\n");
}
if (ret == 'Q')
{
printf("\n");
printf("旗鼓相当,平局\n");
printf("\n");
}
DisplayBoard(board, ROW, COL);
}
break;
default:
printf("输入错误,请重新输入(1/2)\n");
goto flag;
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();//打印菜单
printf("请选择:>\n");
scanf("%d", &input);
int tem = getchar();//将缓存区的字符全部拿走
switch (input)
{
case 1:
printf("\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误请重新输入(1/0)\n");
break;
}
} while (input);
return 0;
}