目录
整体思路与设计
三子棋又叫井字棋,规则为在一个3*3的棋盘里对弈,最后三子一线则为赢。而接下来我们将用C语言来简单实现它。实现结果展示大概为这样,具体实现请看下文
博主使用的是VS2019进行编译,有对该编译器感兴趣或想要下载链接的可以私信博主
首先呢我们先创建一个工程,在此工程中创建三个文件为
game.h 为我们所创建的头文件,里面有我们所需要的所有函数声明
game.c 为我们三子棋游戏的具体实现
test.c 为我们的主函数所在,和实现
写一个代码,我们从它的主函数开始写起,那么我们这个主函数该怎么写呢;我们写一个游戏,首先是不是得有一个游戏界面,得让使用者知道要干些什么;而且得让他有的选择;其次呢万一玩家完了之后还要继续玩呢?当我们知道这些后就可开始test.c的实现了;
void menu()
{
printf("******** 三子棋游戏 ********\n");
printf("******** 1 . 玩游戏 *******\n");
printf("******** 2 . 退出游戏 *******\n");
printf("**规则:一次一子,三子相连为赢\n");
printf("******************************\n");
}
首先我们创建一个menu()的函数来实现菜单的打印
int main()
{
int input = 0;
srand((unsigned int)time(NULL));//产生随机数,与rand()搭配使用,在game()中会用到
do
{
menu();
printf("请选择:>");
scanf("%d", &input);//进行选择
switch (input)
{
case 1:
game();//game()的实现后续会讲到
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择!\n");
break;
}
getchar();//两个getchar(),是为了吃掉回车,后续会讲到具体用处
getchar();
system("cls");//清空前面输出的棋盘,使页面更加整洁(每一局结束后清理)
} while (input);
return 0;
}
这就是我们的主函数,因为博主觉得菜单不算game()函数的具体实现,便放在了test.c里
我们来看一下博主写的test.c
#include "game.h"//我们自己创建的头文件
void menu()
{
printf("******** 三子棋游戏 ********\n");
printf("******** 1 . 玩游戏 *******\n");
printf("******** 2 . 退出游戏 *******\n");
printf("**规则:一次一子,三子相连为赢\n");
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;
}
getchar();
getchar();
system("cls");
} while (input);
return 0;
}
接下来我们来到最难的game()函数的实现了,这里我们采用二维数组来实现
首先我们得对数组初始化,其次呢我们得有个棋盘,然后呢就是下棋过程,分为玩家下棋,和电脑下棋,而每一轮下完棋后,又需要进行判断输赢情况。
那么我们就有了思路,可分为以下几个模块来写:
1.数组的初始化
2.打印棋盘
3.选手输入
4.电脑输入
5.判断输赢
在函数篇讲到函数:先声明后使用
则在头文件game.h里的函数声明如下
#pragma once
#include<stdio.h>
#include<time.h>
#include<windows.h>
#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);
那接下来我们就开始game()函数的实现部分;
1.数组的初始化
在这里我们从最开始结果展示可以发现,最开始是什么都没有·,所以都初始化为空格,数组初始化不懂得可以看看博主对数组篇得讲解
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] = ' ';
}
}
}
2.打印棋盘
我们先来看一下我们所需要得棋盘长什么样子?
接下来我们看一下具体得代码实现
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("|");//因为最后一个字符不用打印'|',所一只用打印col-1次
}
printf("\n");
for (j = 0; j < row; j++)
{
if (i < row - 1)//同理,后一行不打印
{
printf("---");//产生棋盘的分割线
if (j < col - 1)//与上面相同,最后一个不用打印
printf("|");
}
}
printf("\n");
}
}
关于每一步得思路和注释已经写在了代码里,有需要得宝子可以看一下
3.选手输入
选手输入时不但要做出提示,还得对输入的位置进行判断,此处是否能落子,实现代码如下
void PlayerMove(char board[ROW][COL], int row, int col)
{
printf("玩家输入\n");
printf("请输入一个坐标,中间用空格隔开>:");
int x = 0;
int y = 0;
while (1)//若不对可循环输入
{
scanf("%d%d", &x, &y);
if ((x<1 && x>row) || (x<1 && x>col))
printf("非法输入,请重新输入\n");
if (board[x - 1][y - 1] == ' ')//玩家输入的坐标都是从一开始的,而数组的下标是从0开始的,
{ //所以需要减一
board[x - 1][y - 1] = '*';//我们让玩家下的棋子为'*';
break;//输入正确跳出循环
}
else printf("此处已被占用,请重新输入\n");
}
}
测试一下,实现成功
4.电脑输入
电脑输入这里我们将引用前面猜数字游戏所讲的一个知识点,随机数的产生,接下来我们来看看代码的实现
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑输入\n");
while (1)//循环输入,直到输入成功为止
{
int x = rand() % row;//与前面所讲的srand()一起使用,可产生1-row的随机数
int y = rand() % col;//1-col的随机数
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '#';//电脑下棋落子记为'#'
break;//输入成功跳出循环
}
}
}
结果展示可以参考上一张图
5.判断输赢
数据输入了进来,这时候我们就要进行判断游戏是否继续,如果不继续结果是怎么样的?
代码如下:
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 < col; 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[1][1];//返回赢得棋子是*还是#
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
return board[1][1];//返回赢得棋子是*还是#
//平局
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
这个函数里还嵌套了一个IsFull()得函数,用来判断是否所有空格都被填满,代码如下
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;
}
}
return 1;
}
到此为止所有需要得功能都已经写完,接下来我们要将他们组装起来,组装如下
void game()
{
char board[ROW][COL] = { 0 };
InitBoard( board, ROW, COL);//数组初始化
DisplayBoard(board, ROW, COL);//打印最初得棋盘
while (1)
{
PlayerMove(board, ROW, COL);//玩家输入
DisplayBoard(board, ROW, COL);//打印已经改变的棋盘
if (IsWin(board, ROW, COL) != 'C')//判断是否继续游戏
break;//游戏结束跳出循环
ComputerMove(board, ROW, COL);//电脑输入
DisplayBoard(board, ROW, COL);//打印改变得棋盘
if (IsWin(board, ROW, COL) != 'C')//判断是否继续游戏
break;
}
if (IsWin(board, ROW, COL) == '*')
printf("恭喜你,你赢了!!\n");//接受返回值做出判断
if (IsWin(board, ROW, COL) == '#')
printf("很遗憾,你输了!!\n");//接受返回值做出判断
if (IsWin(board, ROW, COL) == 'Q')
printf("平局!!\n");//接受返回值做出判断
}
至此呢,所有代码都已完成,我们来试玩一下
成功实现,但是我们发现,前面堆积太多了,下一次游戏进行十分不美观,这时候博主前面所讲得一个就起作用了 ,有了这一段代码后,只需要你再按一下回车,就可以清除前面所打印的。
以上就是博主的对三子棋游戏的实现,制作不易,各位看官给个三连呗!!!
以上就是博主的对三子棋游戏的实现,制作不易,各位看官给个三连呗!!!
完整代码
game.h
#pragma once
#include<stdio.h>
#include<time.h>
#include<windows.h>
#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);
game.c
#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 < col - 1)
printf("|");
}
printf("\n");
for (j = 0; j < row; j++)
{
if (i < row - 1)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
void PlayerMove(char board[ROW][COL], int row, int col)
{
printf("玩家输入\n");
printf("请输入一个坐标,中间用空格隔开>:");
int x = 0;
int y = 0;
while (1)
{
scanf("%d%d", &x, &y);
if ((x<1 && x>row) || (x<1 && x>col))
printf("非法输入,请重新输入\n");
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else printf("此处已被占用,请重新输入\n");
}
}
void ComputerMove(char board[ROW][COL], int row, int col)
{
printf("电脑输入\n");
while (1)
{
int x = rand() % row;
int y = rand() % col;
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '#';
break;
}
}
}
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;
}
}
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 < col; 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[1][1];
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
return board[1][1];
//平局
if (IsFull(board, row, col) == 1)
{
return 'Q';
}
//继续
return 'C';
}
void game()
{
char board[ROW][COL] = { 0 };
InitBoard( board, ROW, COL);
DisplayBoard(board, ROW, COL);
while (1)
{
PlayerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
if (IsWin(board, ROW, COL) != 'C')
break;
ComputerMove(board, ROW, COL);
DisplayBoard(board, ROW, COL);
if (IsWin(board, ROW, COL) != 'C')
break;
}
if (IsWin(board, ROW, COL) == '*')
printf("恭喜你,你赢了!!\n");
if (IsWin(board, ROW, COL) == '#')
printf("很遗憾,你输了!!\n");
if (IsWin(board, ROW, COL) == 'Q')
printf("平局!!\n");
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
printf("******** 三子棋游戏 ********\n");
printf("******** 1 . 玩游戏 *******\n");
printf("******** 2 . 退出游戏 *******\n");
printf("**规则:一次一子,三子相连为赢\n");
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;
}
getchar();
getchar();
system("cls");
} while (input);
return 0;
}