今天我给大家带来一个小游戏,三子棋的简单实现。跟着本篇文章,你也可以做出属于你自己的三子棋。
游戏的整体思路
1.text.c————用来测试游戏
2.game.c————游戏功能的实现
3.game.h————游戏功能的声明
‘*’代表着玩家下的棋(也表示赢),‘#’代表电脑下的棋(也表示赢),‘Q’表示和棋,‘C’表示继续,
text.c————我们用来测试游戏,我们玩游戏时都会先玩一把,所以我们会选择用do while的循环来解决,当我们第一次进入时,就应该有一个菜单来问我们是否玩游戏,这就用到了我们的menu函数,然后我们可以根据我们选择来选择是否玩游戏。
int main()
{
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出成功\n");
break;
default:
printf("选择错误,重新选择:>\n");
break;
}
} while (input);
return 0;
}
我们定义了一个int类型的临时变量input,然后我们根据input的不同来选择是否进行游戏,当我们选择1时,我们就玩游戏,选择0时就选择退出游戏,如果不是这2个数就重新选择。
void menu()
{
printf("*************************\n");
printf("******** 1.play *******\n");
printf("******** 0.exit *******\n");
printf("*************************\n");
}
void game()
{
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
char ret = 0;
while (1)
{
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
//电脑下
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else
printf("和局\n");
}
我们先定义一个3行3列的二维数组,为了我们代码的可读性,我们就可以将行改为ROW,列对应为COL,这是我们就可以在game.h中#define了
#pragma once
#include
#include
#include
#define ROW 3
#define COL 3
game.h中,我们是把库函数都放在了game.h中,然后我们用#define定义了一下ROW ,COL的数,这样当我们想把棋盘改为5x5的时候,只需要改变game.h的值就可以实现所有的改变。
回到text.c中,我们定义完char类型的二维数组,我们就要初始化它,将二维数组全部初始化为‘ ’。 这时我们就需要在game.h中声明一下InitBoard的函数,将我们的二维数组、行、列全部传进去。
game.h中我们就可以这样声明
void InitBoard(char board[ROW][COL], int row,int col);
然后我们函数的实现就让在了game.c中,
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] = ' ';
}
}
}
我们想,把棋盘初始化后,是不是要显示棋盘,我们就要用到我们的DisPlayBoard的函数,目标是实现这个图。
我们发现第一行是由空格和|组成的,我们row是3,然而我们最后一列没有|,我们就可以分别来实现它,而第二行就是___和|组成的,最后一列也是没有|。这时可以实现DisPlayBoard函数了,代码如下。
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
当然,我们也要在game.h中声明这个函数,当我们实现完显示棋盘的函数,这时我们就可以来实现用户走的函数了,我们可以定义一个PlayerMove的函数,定义一个电脑移动的函数(ComputerMove),我们在game.h中声明一下,然后就可以在game.c中实现了
void PlayerMove(char board[ROW][COL], int row, int col)
{
int pos_x = 0;
int pos_y = 0;
printf("玩家输入:>");
while (1)
{
printf("请输入棋盘坐标\n");
scanf("%d %d", &pos_x, &pos_y);
if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col)
{
if (board[pos_x-1][pos_y-1] == ' ')
{
board[pos_x-1][pos_y-1] = '*';
break;
}
else
{
printf("pos is occupied\n");
}
}
else
{
printf("pos is error\n");
}
}
}
我们定义pos_x和pos_y来表示要走的位置,我们落的棋子就必须在棋盘中,这就有了第一个if的判断,第二个if判断中如果落得那个位置是‘ ’,就代表了那个位置没有人下,我们就可以把“*”下在那个位置,然后挑出循环,如果下的位置有人落了,我们就要重新下,循环一下就可以实现了。但请注意,我下的位置是[pos_x-1][pos_y],这是因为我们的数组下标是从0开始的,而用户玩的时候,以为的1行1列就是我们的0行0列,所以我们都要-1,。
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑输入:>\n");
while (1)
{
int pos_x = rand() % row;//0-row-1
int pos_y = rand() % col;//0-col-1
if (board[pos_x][pos_y] == ' ')
board[pos_x][pos_y] = '#';
break;
}
}
电脑下的棋子当然要下在棋盘内,所以我们用到了%row,表示着0-row-1的位置,我们要在棋盘内随机落子,我们就要用到rand函数,rand函数就要用到srand函数,我们可以把srand放在main函数中,
srand(((unsigned int)time(NULL)));
这个代表着时间戳,我们显示生活中的时间都是一直在走的,这样我们就可以实现随机落子了,我们用srand函数中用到了time的类型我们就把它置位空,类型强转为(unsigned int),注意,我们的srand要把它放在while函数之前,不能放在while函数中,我们可以这样理解,如果我们把srand函数放在whlie函数中,我们是不是每次循环的时候,时间都要重新设定一下,这样就不符合我们的定义了。
然后就是我们的IsWin函数了,我们把board,row,col传参传过去,我们要实现IsWin函数,老方法需要我们在game.h中声明一下,在game.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][1] != ' ') return board[i][0];//返回谁赢 '*' '#' 'Q' 'C' } for (i = 0; i < row; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] &&board[0][i] != ' ') return board[0][i]; } if (board[0][0] == board[1][1] && board[1][1] == board[2][2] &&board[1][1] != ' ') return board[i][i]; if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') return board[1][1]; if ((IsFull(board, row, col)) == 1) return 'Q'; return 'C'; }
我们定义一个int类型的变零i,然后我们用for循环,进入第一个if判断,如果连着3个都相等,而且都不等于‘ ’,我们就可以返回board【i】【0】,代表着谁连3个就谁赢,第二个if判断就是判断列是否相等,第三个和第四个是判断斜对角是否3个连着的。
- 当棋盘满了的时候,我们就返回了‘Q’,代表着和棋,如果上述三个都不满足,就表示继续下棋。
- IsFull函数需要我们遍历一下,用for循环,代码如下,
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 < col; j++) { if (board[i][j] == ' ') return 0; } } //返回为1 if才会进去 return 1; }
如果我们的3行3列棋盘都没有‘ ’的时候就代表着满了返回1,如果有一个等于‘ ’,我们就返回0,我们的IsFull函数就根据我们返回值来判断棋盘是否为空。
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盘为空格
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 ");
while (1)
{
printf("请输入棋盘坐标\n");
scanf("%d %d", &pos_x, &pos_y);
if (pos_x >= 1 && pos_x <= row && pos_y >= 1 && pos_y <= col)
{
if (board[pos_x-1][pos_y-1] == ' ')
{
board[pos_x-1][pos_y-1] = '*';
break;
}
else
{
printf("pos is occupied\n");
}
}
else
{
printf("pos is error\n");
}
}
}
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 < col; j++)
{
if (board[i][j] == ' ')
return 0;
}
}
//返回为1 if才会进去
return 1;
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑输入:>\n");
while (1)
{
int pos_x = rand() % row;//0-row-1
int pos_y = rand() % col;//0-col-1
if (board[pos_x][pos_y] == ' ')
board[pos_x][pos_y] = '#';
break;
}
}
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][1] != ' ')
return board[i][0];//返回谁赢 '*' '#' 'Q' 'C'
}
for (i = 0; i < row; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] &&board[0][i] != ' ')
return board[0][i];
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] &&board[1][1] != ' ')
return board[i][i];
if (board[3][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
return board[1][1];
if ((IsFull(board, row, col)) == 1)
return 'Q';
return 'C';
}
#pragma once
#include
#include
#include
#define ROW 3
#define COL 3
void InitBoard(char board[ROW][COL], int row,int col);
void DisplayBoard(char board[ROW][COL], int row, int col);
void PlayerMove(char board[ROW][COL], int row, int col);
void ComputerMove(char board[ROW][COL], int row, int col);
char IsWin(char board[ROW][COL], int row, int col);
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("*************************\n");
printf("******** 1.play *******\n");
printf("******** 0.exit *******\n");
printf("*************************\n");
}
void game()
{
char board[ROW][COL] = { 0 };
InitBoard(board, ROW, COL);
DisplayBoard(board, ROW, COL);
char ret = 0;
while (1)
{
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
//电脑下
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
ret = IsWin(board, ROW, COL);
if (ret != 'C')
break;
}
if (ret == '*')
printf("玩家赢\n");
else if (ret == '#')
printf("电脑赢\n");
else
printf("和局\n");
}
int main()
{
int input = 0;
srand(((unsigned int)time(NULL)));
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出成功\n");
break;
default:
printf("选择错误,重新选择:>\n");
break;
}
} while (input);
return 0;
}
最后:这样我们就实现了简单的三子棋,当然我们也有问题,当我们的棋盘变成10x10时,我们IsWin的判断就有问题了,我们也只能判断3子棋,如果有兴趣,可以适当改一下代码,让它变成多子棋。