目录
前言
今天给大家带来一个简易的三子棋的代码实现,希望大家喜欢
什么是三子棋?
不知道大家小时候有没有和小伙伴们玩过一种能快速判断输赢的游戏,就是就是拿粉笔在地上画一个“井”字棋盘,然后在棋盘里画上圈或者叉,当棋盘上有任意一行或一列或对角线上出现三个连续的圈或者叉的时候就有人赢了,这其实就是三子棋:
实现的基本流程
1、简易的菜单,可以选择开始游戏或退出游戏。
2、创建一个棋盘并初始化。
3、打印棋盘。
4、玩家下棋和电脑玩家下棋。
5、判断输赢或者平局或者继续下棋。
具体实现步骤
1、分模块实现:
我们要分模块实现,这样会显得代码不会太烦乱,管理起来也比较好,
先创建一个test.c文件,用来进行游戏的测试(也就是真正开始玩游戏)
再创建一个头文件game.h,用来存放关于游戏的各个函数的声明
在创建一个文件game.c,用来存放关于游戏的各个函数的实现
2、创建简易的菜单和主函数的逻辑
在test.c文件中创建一个简易的菜单函数即可:
// 菜单
void menu() {
printf("<<<<<<<<欢迎来到三子棋游戏>>>>>>>>\n");
printf("<<<<<<<<选择1------开始游戏>>>>>>>>\n");
printf("<<<<<<<<选择0------退出游戏>>>>>>>>\n");
}
主函数:
int main() {
int input;
do {
menu(); // 主界面
printf("请选择:\n");
scanf("%d", &input);
switch (input) {
case 1:
game(); // game函数,游戏实现的具体逻辑
break;
case 0:
printf("退出游戏成功!\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
这样跟游戏相关的函数的调用就都放到game函数里就行了。
3、创建棋盘并初始化
创建棋盘放在game函数里:
这里的ROW和COL其实是在头文件game.h用宏定义的常量,
这里使用宏定义的原因主要是提高了代码的可扩展性,以后若想要修改棋盘的大小,就可以直接对宏常量进行修改,非常方便。
有了棋盘之后就要进行初始化了:
// 初始化棋盘
void Init(char 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] = ' '; //全都初始化为空格
}
}
}
4、打印棋盘
// 打印棋盘
void print(char board[ROW][COL], int row, int col) {
int i, j;
for (i = 0; i < row; i++) {
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 < row; j++) {
printf("---");
if (j < col - 1) {
printf("|");
}
}
}
printf("\n"); // 打印完一行,换行
}
printf("\n"); // 为了后续的打印不烦乱打印完后还需要换行
}
最终打印的棋盘像这样子:
5、玩家下棋电脑玩家下棋
5.1玩家下棋
我们通过接收玩家输入的坐标的方式来完成玩家下棋的功能:
// 玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col) {
int x = 0, y = 0;
while (1) {
printf("请输入你要下的坐标:");
scanf("%d %d", &x, &y); // 接收玩家输入的坐标
if ((x < 1 || x - 1 > row) || (y < 1 || y - 1 > col)) { // 判断坐标的合法性
printf("输入坐标有误,请重新输入\n");
continue;
}
if (board[x - 1][y - 1] != ' ') {
printf("坐标已被占用,请重新输入\n");
continue;
}
else if (board[x - 1][y - 1] == ' ') {
board[x - 1][y - 1] = 'o'; // 将棋下入棋盘
printf("你走>\n");
print(board, ROW, COL); //打印棋盘,让玩家看到所走的每一步
break;
}
}
}
5.2电脑玩家下棋
我们让电脑玩家随机随机下棋:
// 电脑玩家下棋
void ComputerMove(char board[ROW][COL], int row, int col) {
printf("电脑玩家思考中……\n"); // 提示以下,增加游戏的体验感
Sleep(1500); // 模拟电脑玩家思考过程,让程序先暂停一会儿
while (1) {
int x = rand() % row; // 使用随机数函数生成坐标,
int y = rand() % col; // 取余是为了保证坐标的合法性(保证得到的坐标范围在0-row - 1内)
if (board[x][y] != ' ') {
continue;
}
else if (board[x][y] == ' ') {
printf("电脑玩家走>\n");
board[x][y] = 'x'; // 将棋下如棋盘
print(board, ROW, COL); // 打印棋盘,让玩家看到所走的每一步
break;
}
}
}
这里使用到了Sleep和rand函数,那我们就要引相应的头文件,
Sleep对应的头文件是windows.h:
rand对应的头文件是,且rand函数在使用时要提前调用srand函数,所以我们得在main函数中调用一次srand函数:
我们这里使用time函数的返回值座位随机数的生成器,所以我们还要因一个头文件time.h:
因为在test.c和game.c中我们都要引游戏相关的头文件game.h,所以其他头文件的引入我们就可以都放在game.h文件中。
6、判断输赢或平局或继续
我们将判断输赢的函数的返回值设置成char类型,规定返回的是‘o’表示玩家胜利,返回的是‘x’则表示电脑玩家胜利,返回的是‘q’则表示是平局,返回的是‘c’则表示继续下棋。
判断输赢其实就是判断任意一行或任意一列或对角线上有三个连续的圈或者叉,平局其实就是当棋盘已满但还没有分出输赢:
// 判断输赢
char IsWin(char board[ROW][COL], int row, int col) {
int i;
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][1];
}
// 判断列
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];
}
}
// 判断是否平局
if (IsFull(board, row, col) == 1) {
return 'q';
}
// 继续
return 'c';
}
7、判断棋盘是否已满
判断平局要用到判断是否已满的函数,其实这个函数的实现非常简单,我们规定返回1表示棋盘已满,返回0表示没满:
// 判断棋盘是否已满
int IsFull(char board[ROW][COL], int row, int col) {
int i, j;
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
if (board[i][j] == ' ') {
return 0;
}
}
}
return 1;
}
具体运行逻辑
有了各种方法之后我们还需要对游戏的运行逻辑下功夫,以更好的提升用户的使用体验,这当然是要放在game函数里面实现啦:
// 游戏
void game() {
char board[ROW][COL];
// 初始化棋盘
Init(board, ROW, COL);
// 打印棋盘
printf("游戏开始!\n");
print(board, ROW, COL);
// 开始下棋
char result; // 用来接收输赢的结果
while (1) { // 用循环来实现”人机对战“的逻辑
PlayerMove(board, ROW, COL);
result = IsWin(board, ROW, COL);
if (result == 'o') {
printf("恭喜你,你赢了!\n");
char chose; // 接收赢后的选择
printf("是否再玩一局? y/n:");
getchar();
scanf("%c", &chose);
if (chose == 'y') {
Init(board, ROW, COL); // 清空棋盘,开始新的一局
printf("新游戏开始!\n");
print(board, ROW, COL);
continue;
}
else if (chose == 'n') {
printf("返回主界面\n"); // 返回主界面后可以选择结束游戏
break;
}
}
else if (result == 'q') {
printf("抱歉,这局是平局\n");
char chose;
printf("是否再玩一局? y/n:");
getchar();
scanf("%c", &chose);
if (chose == 'y') {
Init(board, ROW, COL);
printf("新游戏开始!\n");
print(board, ROW, COL);
continue;
}
else if (chose == 'n') {
printf("返回主界面\n");
break;
}
}
ComputerMove(board, ROW, COL);
result = IsWin(board, ROW, COL);
if (result == 'x') {
printf("很遗憾,你输给了电脑玩家!\n");
char chose;
printf("是否再玩一局? y/n:");
getchar();
scanf("%c", &chose);
if (chose == 'y') {
Init(board, ROW, COL);
printf("新游戏开始!\n");
print(board, ROW, COL);
continue;
}
else if (chose == 'n') {
printf("返回主界面\n");
break;
}
}
else if (result == 'q') {
printf("抱歉,这局是平局\n");
char chose;
printf("是否再玩一局? y/n:");
getchar();
scanf("%c", &chose);
if (chose == 'y') {
Init(board, ROW, COL);
printf("新游戏开始!\n");
print(board, ROW, COL);
continue;
}
else if (chose == 'n') {
printf("返回主界面\n");
break;
}
}
}
}
玩上几把
1、玩家赢
2、电脑玩家赢
整体代码逻辑
1、头文件game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define ROW 3
#define COL 3
void Init(char board[ROW][COL], int row, int col);
void print(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);
int IsFull(char board[ROW][COL], int row, int col);
void game();
2、game.c
#include "game1.h"
// 初始化棋盘
void Init(char 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 print(char board[ROW][COL], int row, int col) {
int i, j;
for (i = 0; i < row; i++) {
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 < row; j++) {
printf("---");
if (j < col - 1) {
printf("|");
}
}
}
printf("\n"); // 打印完一行,换行
}
printf("\n"); // 为了后续的打印不烦乱打印完后还需要换行
}
// 玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col) {
int x = 0, y = 0;
while (1) {
printf("请输入你要下的坐标:");
scanf("%d %d", &x, &y); // 接收玩家输入的坐标
if ((x < 1 || x - 1 > row) || (y < 1 || y - 1 > col)) { // 判断坐标的合法性
printf("输入坐标有误,请重新输入\n");
continue;
}
if (board[x - 1][y - 1] != ' ') {
printf("坐标已被占用,请重新输入\n");
continue;
}
else if (board[x - 1][y - 1] == ' ') {
board[x - 1][y - 1] = 'o'; // 将棋下入棋盘
printf("你走>\n");
print(board, ROW, COL);
break;
}
}
}
// 电脑玩家下棋
void ComputerMove(char board[ROW][COL], int row, int col) {
printf("电脑玩家思考中……\n"); // 提示以下,增加游戏的体验感
Sleep(1500); // 模拟电脑玩家思考过程,让程序先暂停一会儿
while (1) {
int x = rand() % row; // 使用随机数函数生成坐标,
int y = rand() % col; // 取余是为了保证坐标的合法性(保证得到的坐标范围在0-row - 1内)
if (board[x][y] != ' ') {
continue;
}
else if (board[x][y] == ' ') {
printf("电脑玩家走>\n");
board[x][y] = 'x'; // 将棋下如棋盘
print(board, ROW, COL);
break;
}
}
}
// 判断棋盘是否已满
int IsFull(char board[ROW][COL], int row, int col) {
int i, j;
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;
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][1];
}
// 判断列
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];
}
}
// 判断是否平局
if (IsFull(board, row, col) == 1) {
return 'q';
}
// 继续
return 'c';
}
// 游戏
void game() {
char board[ROW][COL];
// 初始化棋盘
Init(board, ROW, COL);
// 打印棋盘
printf("游戏开始!\n");
print(board, ROW, COL);
// 开始下棋
char result; // 用来接收输赢的结果
while (1) { // 用循环来实现”人机对战“的逻辑
PlayerMove(board, ROW, COL);
result = IsWin(board, ROW, COL);
if (result == 'o') {
printf("恭喜你,你赢了!\n");
char chose; // 接收赢后的选择
printf("是否再玩一局? y/n:");
getchar();
scanf("%c", &chose);
if (chose == 'y') {
Init(board, ROW, COL); // 清空棋盘,开始新的一局
printf("新游戏开始!\n");
print(board, ROW, COL);
continue;
}
else if (chose == 'n') {
printf("返回主界面\n"); // 返回主界面后可以选择结束游戏
break;
}
}
else if (result == 'q') {
printf("抱歉,这局是平局\n");
char chose;
printf("是否再玩一局? y/n:");
getchar();
scanf("%c", &chose);
if (chose == 'y') {
Init(board, ROW, COL);
printf("新游戏开始!\n");
print(board, ROW, COL);
continue;
}
else if (chose == 'n') {
printf("返回主界面\n");
break;
}
}
ComputerMove(board, ROW, COL);
result = IsWin(board, ROW, COL);
if (result == 'x') {
printf("很遗憾,你输给了电脑玩家!\n");
char chose;
printf("是否再玩一局? y/n:");
getchar();
scanf("%c", &chose);
if (chose == 'y') {
Init(board, ROW, COL);
printf("新游戏开始!\n");
print(board, ROW, COL);
continue;
}
else if (chose == 'n') {
printf("返回主界面\n");
break;
}
}
else if (result == 'q') {
printf("抱歉,这局是平局\n");
char chose;
printf("是否再玩一局? y/n:");
getchar();
scanf("%c", &chose);
if (chose == 'y') {
Init(board, ROW, COL);
printf("新游戏开始!\n");
print(board, ROW, COL);
continue;
}
else if (chose == 'n') {
printf("返回主界面\n");
break;
}
}
}
}
3、test.c
#include "game1.h"
// 菜单
void menu() {
printf("<<<<<<<<欢迎来到三子棋游戏>>>>>>>>\n");
printf("<<<<<<<<选择1------开始游戏>>>>>>>>\n");
printf("<<<<<<<<选择0------退出游戏>>>>>>>>\n");
}
int main() {
int input;
srand((unsigned int)time(NULL));
do {
menu(); // 主界面
printf("请选择:\n");
scanf("%d", &input);
switch (input) {
case 1:
game(); // game函数,游戏实现的具体逻辑
break;
case 0:
printf("退出游戏成功!\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
最后也是最重要的
好啦,今天的焚香就到这里的,制作不易,如果大家觉得我写的还可以的话,请求大家动动小手给我点上一个小小小的赞啦,谢谢大家!