①前言
作为一个C语言初学者,当学会一些基础知识后就可以自己动手制作一个三子棋小游戏。与平常的三子棋游戏不同的是,本篇博客将会带领你实现自定义棋盘大小的三子棋。②
②效果演示
③实现思路&流程
1.创建菜单函数,选择play或exit。
2.创建二维棋盘数组,并将棋盘初始化。
3.打印棋盘,显示游戏棋盘,给玩家选择坐标下棋。
进入循环
{
4.玩家下棋,并打印棋盘,打印棋盘前先清空屏幕,使界面看起来更加舒适(玩家输入行、列坐标,'O'=玩家棋子。
5.判断玩家是否获胜,判断是否继续进行游戏。
6.电脑下棋,并打印棋盘,打印棋盘前先清空屏幕,'X'=电脑棋子。
7.判断电脑是否获胜,判断是否继续进行游戏。
}
8.回到步骤1。
④实现过程
1.创建test.c 、gamg.c源文件 和 game.h头文件 三个文件
①这样做的目的是便于对代码进行管理,便于观察。用到的头文件和函数声明放在game.h文件中。
②main函数和游戏主函数以及颜色函数放在test.c文件中。
③游戏功能函数放在game.c文件中。
2.在game.h文件中引需要用到的头文件和定义棋盘的行、列
使用宏定义行、列的好处是,当要修改棋盘的大小时,只要修改宏定义就行,不需要全部代码都改一遍。!!!
ROW代表行,COL代表列,<time.h>头文件用于随机数的生成,<Window.h>头文件用于改变棋子的颜色。
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
#define ROW 10//行
#define COL 10//列
//多出来的一行一列用来存放数字,以便于找坐标
#define ROWS ROW+1
#define COLS COL+1
3.创建main函数
int main()
{
srand((unsigned)time(NULL));//用于随机数的生成
int input = 0;//用户做出选择,1表示开始游戏,0表示退出游戏
do
{
menu();//菜单函数
printf("请选择:> ");
scanf("%d", &input);
system("cls");//清空屏幕,清除上次留下的信息
switch (input)
{
case 1:
//输入1,进入游戏
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择 ");
break;
}
} while (input);
return 0;
}
4.创建菜单函数
void menu()//菜单函数
{
printf("\t\t\t\t\t\t*******************************\n");
printf("\t\t\t\t\t\t****** 三子棋 ******\n");
printf("\t\t\t\t\t\t****** 1.play ******\n");
printf("\t\t\t\t\t\t****** 2.exit ******\n");
printf("\t\t\t\t\t\t*******************************\n");
}
5.实现游戏功能函数
1.初始化棋盘
把落子位置全部置成空格,剩下的位置置成行数字和列数字
void Initbroad(char broad[ROWS][COLS], int rows, int cols)//初始化棋盘
{
//将下棋区域全部赋上空格' '
for (int i = 1; i < rows; i++)
{
for (int j = 1; j < cols; j++)
{
broad[i][j] = ' ';
}
}
//将第一行赋为0,1,2,3,4……
for (int i = 0; i < cols; i++)
{
broad[0][i] = i;
}
//将第一列赋为1,2,3,4,5……
for (int i = 1; i < rows; i++)
{
broad[i][0] = i;
}
}
2.打印棋盘
void Displaybroad(char broad[ROWS][COLS], int rows, int cols)//打印棋盘
{
//打印第一行的数字
for (int i = 0; i < rows; i++)
{
printf(" %2d ", broad[0][i]);
if (i < rows - 1)
{
printf("|");
}
}
printf("\n");
for (int i = 1; i < rows; i++)
{
//打印分隔线
for (int i = 0; i < rows; i++)
{
printf("----");
if (i < rows - 1)
{
printf("|");
}
}
printf("\n");
printf(" %2d ", broad[i][0]);//打印第一列的数字
for (int j = 1; j < cols; j++)
{
printf("|");
if (broad[i][j] == 'O')//如果检测到下个打印的字符为'O',则改变输出字符的颜色
{
color(2);//将输出颜色变为绿色
printf(" %2c ", broad[i][j]);
color(15);//输出完后,再将输出颜色变为原来的颜色
continue;//跳出本次循环
}
if (broad[i][j] == 'X')//如果检测到下个打印的字符为'X',则改变输出字符的颜色
{
color(6);//将输出颜色变为黄色
printf(" %2c ", broad[i][j]);
color(15);//输出完后,再将输出颜色变为原来的颜色
continue;//跳出本次循环
}
printf(" %2c ", broad[i][j]);
}
printf("\n");
}
}
打印棋盘过程。
3.玩家下棋函数
void Playermove(char broad[ROWS][COLS], int row, int col)//玩家下棋
{
printf("玩家走\n");
int x = 0;//行坐标
int y = 0;//列坐标
while (1)
{
printf("请选择你的坐标:> ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)//如果输入坐标在棋盘内,则成立
{
if (broad[x][y] == ' ')
{
broad[x][y] = 'O';
break;
}
else
{
printf("该坐标已被占用,请重新选择\n");
}
}
else
{
printf("没有此坐标,请重新输入\n");
}
}
}
4.电脑下棋函数
void Computermove(char broad[ROWS][COLS], int row, int col)//电脑下棋
{
printf("电脑走\n");
while (1)
{
int x = rand() % row + 1;//随机生成1~row的数字
int y = rand() % col + 1;//随机生成1~col的数字
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (broad[x][y] == ' ')
{
broad[x][y] = 'X';
break;
}
}
}
}
5.判断输赢函数
判断算法图示
1.判断行
2.判断列
3.判断斜向
char Jugdewin(char broad[ROWS][COLS], int row, int col)//判断输赢
{
for (int i = 1; i <= row; i++)//控制每一行和每一列
{
for (int j = 1; j <= col - 2; j++)
{
//判断行是否符合
if (broad[i][j] == broad[i][j + 1] && broad[i][j + 1] == broad[i][j + 2] && broad[i][j] != ' ')
{
return broad[i][j];
}
//判断列是否符合
if (broad[j][i] == broad[j + 1][i] && broad[j + 1][i] == broad[j + 2][i] && broad[j][i] != ' ')
{
return broad[j][i];
}
}
}
//判断斜向是否符合
for (int i = 1; i <= row - 2; i++)
{
for (int j = 1; j <= col - 2; j++)
{
if (broad[i][j] == broad[i + 1][j + 1] && broad[i + 1][j + 1] == broad[i + 2][j + 2] && broad[i + 1][j + 1] != ' ')
{
return broad[i + 1][j + 1];
}
if (broad[i][row - j + 1] == broad[i + 1][row - j] && broad[i + 1][row - j] == broad[i + 2][row - j - 1] && broad[i + 1][row - j] != ' ')
{
return broad[i + 1][row - j];
}
}
}
//检查棋盘是否已满,如果不是,则返回 u
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= row; j++)
{
if (broad[i][j] == ' ')
{
return 'u';
}
}
}
return 'f';
}
如果玩家获胜,则返回'O',如果电脑获胜,则返回'X',如果棋盘已满,则返回'f',如果都不符合,则说明没人获胜,棋盘也没满,则返回'u‘。
6.实现游戏主体函数
1.实现输入变化颜色函数
void color(int num)//颜色函数,将'X','O',赋上不同的颜色,以便于观察
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), num);
}
2.实现游戏主体函数
void game()
{
char ret;//用于接受“判断输赢函数”的返回值,返回"O",则玩家获胜,返回"X",则电脑获胜,返回'f',则棋盘已满,平局,返回'u’,则继续游戏
char broad[ROWS][COLS];//二维数组棋盘
Initbroad(broad, ROWS, COLS);//初始化棋盘
Displaybroad(broad, ROWS, COLS);//打印棋盘
while (1)
{
Playermove(broad, ROW, COL);//玩家下棋
system("cls");
Displaybroad(broad, ROWS, COLS);//打印棋盘
ret = Jugdewin(broad, ROW, COL);//判断输赢
if (ret != 'u')//如果Jugdewin不等于'u',则游戏结束,跳出循环
{
break;
}
Computermove(broad, ROW, COL);//电脑下棋
system("cls");
Displaybroad(broad, ROWS, COLS);//打印棋盘
ret = Jugdewin(broad, ROW, COL);//判断输赢
if (ret != 'u')//如果Jugdewin不等于'u',则游戏结束,跳出循环
{
break;
}
}
if (ret == 'O')
{
printf("玩家获胜\n");
}
else if (ret == 'X')
{
printf("电脑获胜\n");
}
else
{
printf("平局\n");
}
}
⑤源代码
1.game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<Windows.h>
#define ROW 10//行
#define COL 10//列
//多出来的一行一列用来存放数字,以便于找坐标
#define ROWS ROW+1
#define COLS COL+1
void Initbroad(char broad[ROWS][COLS], int rows, int cols);//初始化棋盘
void Displaybroad(char broad[ROWS][COLS], int rows, int cols);//打印棋盘
void Playermove(char broad[ROWS][COLS], int row, int col);//玩家下棋
void Computermove(char broad[ROWS][COLS], int row, int col);//电脑下棋
char Jugdewin(char broad[ROWS][COLS], int row, int col);//判断输赢
2.test.c
#include"game.h"
void menu()//菜单函数
{
printf("\t\t\t\t\t\t*******************************\n");
printf("\t\t\t\t\t\t****** 三子棋 ******\n");
printf("\t\t\t\t\t\t****** 1.play ******\n");
printf("\t\t\t\t\t\t****** 2.exit ******\n");
printf("\t\t\t\t\t\t*******************************\n");
}
void color(int num)//颜色函数,将'X','O',赋上不同的颜色,以便于观察
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), num);
}
void game()
{
char ret;//用于接受“判断输赢函数”的返回值,返回"O",则玩家获胜,返回"X",则电脑获胜,返回'f',则棋盘已满,平局,返回'u’,则继续游戏
char broad[ROWS][COLS];//二维数组棋盘
Initbroad(broad, ROWS, COLS);//初始化棋盘
Displaybroad(broad, ROWS, COLS);//打印棋盘
while (1)
{
Playermove(broad, ROW, COL);//玩家下棋
system("cls");
Displaybroad(broad, ROWS, COLS);//打印棋盘
ret = Jugdewin(broad, ROW, COL);//判断输赢
if (ret != 'u')//如果Jugdewin不等于'u',则游戏结束,跳出循环
{
break;
}
Computermove(broad, ROW, COL);//电脑下棋
system("cls");
Displaybroad(broad, ROWS, COLS);//打印棋盘
ret = Jugdewin(broad, ROW, COL);//判断输赢
if (ret != 'u')//如果Jugdewin不等于'u',则游戏结束,跳出循环
{
break;
}
}
if (ret == 'O')
{
printf("玩家获胜\n");
}
else if (ret == 'X')
{
printf("电脑获胜\n");
}
else
{
printf("平局\n");
}
}
int main()
{
srand((unsigned)time(NULL));//用于随机数的生成
int input = 0;//用户做出选择,1表示开始游戏,0表示退出游戏
do
{
menu();//菜单函数
printf("请选择:> ");
scanf("%d", &input);
system("cls");//清空屏幕,清除上次留下的信息
switch (input)
{
case 1:
//输入1,进入游戏
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择 ");
break;
}
} while (input);
return 0;
}
3.game.c
#include"game.h"
void Initbroad(char broad[ROWS][COLS], int rows, int cols)//初始化棋盘
{
//将下棋区域全部赋上空格' '
for (int i = 1; i < rows; i++)
{
for (int j = 1; j < cols; j++)
{
broad[i][j] = ' ';
}
}
//将第一行赋为0,1,2,3,4……
for (int i = 0; i < cols; i++)
{
broad[0][i] = i;
}
//将第一列赋为1,2,3,4,5……
for (int i = 1; i < rows; i++)
{
broad[i][0] = i;
}
}
void Displaybroad(char broad[ROWS][COLS], int rows, int cols)//打印棋盘
{
//打印第一行的数字
for (int i = 0; i < rows; i++)
{
printf(" %2d ", broad[0][i]);
if (i < rows - 1)
{
printf("|");
}
}
printf("\n");
for (int i = 1; i < rows; i++)
{
//打印分隔线
for (int i = 0; i < rows; i++)
{
printf("----");
if (i < rows - 1)
{
printf("|");
}
}
printf("\n");
printf(" %2d ", broad[i][0]);//打印第一列的数字
for (int j = 1; j < cols; j++)
{
printf("|");
if (broad[i][j] == 'O')//如果检测到下个打印的字符为'O',则改变输出字符的颜色
{
color(2);//将输出颜色变为绿色
printf(" %2c ", broad[i][j]);
color(15);//输出完后,再将输出颜色变为原来的颜色
continue;//跳出本次循环
}
if (broad[i][j] == 'X')//如果检测到下个打印的字符为'X',则改变输出字符的颜色
{
color(6);//将输出颜色变为黄色
printf(" %2c ", broad[i][j]);
color(15);//输出完后,再将输出颜色变为原来的颜色
continue;//跳出本次循环
}
printf(" %2c ", broad[i][j]);
}
printf("\n");
}
}
void Playermove(char broad[ROWS][COLS], int row, int col)//玩家下棋
{
printf("玩家走\n");
int x = 0;//行坐标
int y = 0;//列坐标
while (1)
{
printf("请选择你的坐标:> ");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)//如果输入坐标在棋盘内,则成立
{
if (broad[x][y] == ' ')
{
broad[x][y] = 'O';
break;
}
else
{
printf("该坐标已被占用,请重新选择\n");
}
}
else
{
printf("没有此坐标,请重新输入\n");
}
}
}
void Computermove(char broad[ROWS][COLS], int row, int col)//电脑下棋
{
printf("电脑走\n");
while (1)
{
int x = rand() % row + 1;//随机生成1~row的数字
int y = rand() % col + 1;//随机生成1~col的数字
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (broad[x][y] == ' ')
{
broad[x][y] = 'X';
break;
}
}
}
}
char Jugdewin(char broad[ROWS][COLS], int row, int col)//判断输赢
{
for (int i = 1; i <= row; i++)//控制每一行和每一列
{
for (int j = 1; j <= col - 2; j++)
{
//判断行是否符合
if (broad[i][j] == broad[i][j + 1] && broad[i][j + 1] == broad[i][j + 2] && broad[i][j] != ' ')
{
return broad[i][j];
}
//判断列是否符合
if (broad[j][i] == broad[j + 1][i] && broad[j + 1][i] == broad[j + 2][i] && broad[j][i] != ' ')
{
return broad[j][i];
}
}
}
//判断斜向是否符合
for (int i = 1; i <= row - 2; i++)
{
for (int j = 1; j <= col - 2; j++)
{
if (broad[i][j] == broad[i + 1][j + 1] && broad[i + 1][j + 1] == broad[i + 2][j + 2] && broad[i + 1][j + 1] != ' ')
{
return broad[i + 1][j + 1];
}
if (broad[i][row - j + 1] == broad[i + 1][row - j] && broad[i + 1][row - j] == broad[i + 2][row - j - 1] && broad[i + 1][row - j] != ' ')
{
return broad[i + 1][row - j];
}
}
}
//检查棋盘是否已满,如果不是,则返回 u
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= row; j++)
{
if (broad[i][j] == ' ')
{
return 'u';
}
}
}
return 'f';
}
⑥结语
创作不易,如果对你有帮助,记得点赞哟!!!