⚡⚡⚡三子棋小游戏
作者:Shining-point
作者的博客主页:Shining-point的博客
如果觉得博主的博客写的不错或者有所收获的话,希望大家多多🚀点赞 🚀评论🚀收藏。你们的支持是我的最大动力,不驰于空想,不骛于虚声,我们一起加油!!!
博文内容有误均可在评论中指出,教学相长!!!
对了对了,如果对猜数字游戏感兴趣的话,不妨看看博主的这一篇:C语言和猜数字小游戏,好啦,让我们开始吧!
🌟写在前面
C语言编程学完数组能写什么,不妨来写一个三子棋小游戏吧,一方面巩固所学知识,另一方面锻炼自己的逻辑思维和编程能力。不过我想这对编程初学者还是有一定难度的,所以这一次就让我来带你们写写看吧,多多指教啦!
Ⅰ.游戏规则
三子棋是一种民间传统游戏,又叫九宫棋、圈圈叉叉、一条龙、井字棋等。将正方形对角线连起来,相对两边依次摆上三个双方棋子,只要将自己的三个棋子走成一条线,对方就算输了。但是,有很多时候会出现和棋的情况。相信这是多数人的童年回忆,那么用代码如何实现呢?
Ⅱ.游戏逻辑
逻辑顺序:
1.打印菜单,玩家选择开始或者退出游戏
2.初始化棋盘
3.打印棋盘
4.玩家下棋并打印棋子
5.电脑下棋并打印棋子
6.判断输赢
Ⅲ.游戏具体代码实现
ⅰ.编写代码前的准备
创建test.c文件(用于测试游戏逻辑)
创建game.c文件(用于实现游戏功能)
创建game.h文件(用于自定义头文件和函数声明)
ⅱ.打印菜单
//该代码位于test.c文件中//
void menu() //使用自定义menu()函数来打印菜单,不需返回值故使用void
{
printf("****************************************\n");
printf("**************** 1.play ****************\n"); //选择1开始游戏
printf("**************** 0.exit ****************\n"); //选择0退出游戏
printf("****************************************\n");
}
ⅲ.开始或退出游戏
//该代码位于test.c文件中//
#include "game.h" //将所需的头文件和函数声明置于game.h文件中,故此处引用game.h文件即可
int main()
{
srand((unsigned int)time(NULL));//设置随机数的生成起点
int input = 0;
do //游戏至少要玩一次,故使用do while循环
{
menu(); //此处调用自定义menu函数用于打印菜单
printf("请选择:>");
scanf("%d", &input);
switch (input) //switch语句用于选择开始游戏or退出游戏
{
case 1:
game(); //调用自定义game函数执行游戏主逻辑
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while(input);
return 0;
}
ⅳ.初始化棋盘
//该代码位于test.c文件中//
void game() //自定义game函数,不需返回值故使用void
{
char board[ROW][COL] = { 0 };
//自定义初始化棋盘的函数initboard
initboard(board, ROW, COL);
}
//该代码位于game.c文件中//
#include "game.h" //自定义包含game.h头文件,因为要用到它声明的函数
//使用define定义的常量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] = ' ';
}
}
}
//该代码位于game.h文件中//
#pragma once //编译器自动添加,用于防止头文件被重复包含
#include <stdio.h> //该处已包含头文件,故下文不在重复包含
#include <stdlib.h> //该处已包含头文件,故下文不在重复包含
#include <time.h> //该处已包含头文件,故下文不在重复包含
//define定义ROW的值为3,COL的值为3,即定义了一个3✖3的棋盘,要想更改棋盘大小只需更改此处即可
#define ROW 3
#define COL 3
//初始化棋盘
void initboard(char board[ROW][COL], int row, int col);
ⅴ.打印棋盘
//该代码位于test.c文件中//
void game()
{
char board[ROW][COL] = { 0 };
//自定义打印棋盘的函数displayboard
displayboard(board, ROW, COL);
}
//该代码位于game.c文件中//
#include "game.h"
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) //最后一列不打印,所以j<col-1
{
printf("|");
}
}
printf("\n"); //打印完一行换行
if (i < row - 1) //最后一行不打印,所以i<row-1
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|"); 最后一列不打印,所以j<col-1
}
}
printf("\n"); //打印完一行换行
}
}
}
//该代码位于game.h文件中//
//打印棋盘
void displayboard(char board[ROW][COL], int row, int col);
ⅵ.玩家下棋并打印棋子
//该代码位于test.c文件中//
void game()
{
while(1) //一直下直到决出胜负
{
//自定义玩家下棋的函数playermove
playermove(board, ROW, COL);
//打印棋子
displayboard(board, ROW, COL);
}
}
//该代码位于game.c文件中//
void playermove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋:>\n");
while (1)
{
printf("请输入坐标:>");
scanf("%d%d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) //判断棋子是否落在棋盘内
{
if (board[x - 1][y - 1] == ' ') //判断落子位置是否已有棋子
{ //x-1,y-1是为了如果玩家输入1,1,则在二维数组0,0处落子
board[x - 1][y - 1] = '*'; //打印玩家棋子 *
break; //跳出循环
}
else
{
printf("该处已经被下过咯,请选择其他位置\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
//该代码位于game.h文件中//
//玩家下棋
void playermove(char board[ROW][COL], int row, int col);
ⅶ.电脑下棋并打印棋子
//该代码位于test.c文件中//
void game()
{
while(1) //一直下直到决出胜负
{
//自定义电脑下棋的函数computermove
computermove(board, ROW, COL);
//打印棋子
displayboard(board, ROW, COL);
}
}
//该代码位于game.c文件中//
void computermove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
int x = 0;
int y = 0;
while (1)
{
//生成棋盘大小范围内的随机数,随机落子
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ') //判断落子位置是否已有棋子
{
board[x][y] = '#'; //打印电脑棋子 #
break; //跳出循环
}
}
}
//该代码位于game.h文件中//
//电脑下棋
void computermove(char board[ROW][COL], int row, int col);
ⅷ.判断输赢
//该代码位于test.c文件中//
void game()
{
char ret = 0;
while(1)
{
//自定义判断输赢函数iswin
ret = iswin(board, ROW, COL);
//每一步都要判断是否继续下棋,输、赢、平局均跳出循环
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
displayboard(board, ROW, COL) //一局结束,重新打印棋盘
}
//该代码位于game.c文件中//
//自定义判断棋盘是否满的函数isfull
//满了返回1
//不满返回0
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][1] != ' ')
{
return board[i][1]; //该处是谁的棋子谁就赢
}
}
//再判断列
int j = 0;
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
{
return board[1][j]; //该处是谁的棋子谁就赢
}
}
//最后判断对角线
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))
{
return 'Q';
}
//游戏继续
//棋盘未满且未决出胜负
return 'C';
}
//该代码位于game.h文件中//
//判断输赢
//玩家赢 - 输出'*'
//电脑赢 - 输出'#'
//平局 - 输出'Q'
//继续 - 输出'C'
char iswin(char board[ROW][COL], int row, int col);
Ⅳ.游戏完整代码
ⅰ.test.c内代码
#include "game.h"
void menu()
{
printf("****************************************\n");
printf("**************** 1.play ****************\n");
printf("**************** 0.exit ****************\n");
printf("****************************************\n");
}
void game()
{
char ret = 0;
char board[ROW][COL] = { 0 };
initboard(board, ROW, COL);
displayboard(board, ROW, COL);
while (1)
{
playermove(board, ROW, COL);
ret = iswin(board, ROW, COL);
if (ret != 'C')
{
break;
}
displayboard(board, ROW, COL);
computermove(board, ROW, COL);
ret = iswin(board, ROW, COL);
if (ret != 'C')
{
break;
}
displayboard(board, ROW, COL);
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
displayboard(board, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
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;
}
ⅱ.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");
if (i < row - 1)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
}
}
}
void playermove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋:>\n");
while (1)
{
printf("请输入坐标:>");
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("该处已经被下过咯,请选择其他位置\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}
void computermove(char board[ROW][COL], int row, int col)
{
printf("电脑下棋:>\n");
int x = 0;
int y = 0;
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
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][1] != ' ')
{
return board[i][1];
}
}
int j = 0;
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[1][j] != ' ')
{
return board[1][j];
}
}
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))
{
return 'Q';
}
return 'C';
}
ⅲ.game.h内代码
#include <stdio.h>
#include <stdlib.h>
#include <time.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);
Ⅴ.游戏玩法视频
三子棋游戏玩法
Ⅵ.该三子棋存在的缺陷
⚠ 首当其冲的便是电脑的随机落子,这会导致电脑无法对玩家做出有效的拦截,一切全凭运气,也就是所谓的人工智障,优化需要更加高级的算法
⚠ 其二是对三子棋输赢的判断,该处把判断部分的代码写死了,导致只能判断3×3棋盘上三子棋的输赢
⚠ 其三是对平局的判断,只有当棋盘下满了才会判为平局,这没什么问题,只是有时候不需要下满就已经知道是平局了,属于优化代码吧
当然了,博主的这篇三子棋充当闲暇时的消遣还是够的,毕竟谁不喜欢人工智障呢(doge),博主后期有想法了会对代码进行优化的,学习就是积累的过程嘛!😆😆😆
🌟写在最后
或许我们走那么远,不是为了看风景,而是为了去天地的尽头会一会自己。因为只有在那样遥远的地方,你才能把喧嚣的人世抛在身后。 |