一.自定义头文件(game.h)
放入源文件需要用到的标准库头文件和函数的声明
ROW 和COL为棋盘的行和列,三子棋嘛,肯定为3啦
#pragma once
#include<stdio.h>
#include<String.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 ComputerBoard(char board[ROW][COL], int row, int col);
char IsWin(char board[ROW][COL], int row, int col);
二.源文件(test.c和game.c)
1.test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu() {
printf("***********************************\n");
printf("************1.开始游戏*************\n");
printf("************0.退出游戏*************\n");
printf("***********************************\n");
}
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
break;
}
ComputerBoard(board, ROW, COL);//人机输入坐标
DisplayBoard(board, ROW, COL);//再显示一边棋盘当前的情况
if (IsWin(board, ROW, COL) != 'C') {//人机输入坐标后再判断一下满没满或者双方有没有赢的,满足就break
break;
}
}
if (IsWin(board, ROW, COL) == '*') {
printf("玩家赢\n");
}
else if (IsWin(board, ROW, COL) == '#') {
printf("电脑玩家赢\n");
}
else if (IsWin(board, ROW, COL) == 'D') {
printf("平局\n");
}
}
int main() {
int input=0;
srand((unsigned int)time(NULL));
do {
menu();
printf("请输入:");
scanf("%d", &input);
switch(input){
case 1:
printf("进入游戏\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入:\n");
}
} while (input);
return 0;
}
(1)void game()解释
1.先创建一个游戏面板二维数组
字符型的
char board[ROW][COL] = {0};
2.初始化棋盘
InitBoard(board,ROW,COL);
3.显示棋盘
在真正开始游戏之前肯定得先给玩家看一下棋盘滴啦
DisplayBoard(board, ROW, COL);//显示棋盘
4.while()循环
在玩家输入坐标之后
判断一下棋盘是否满了或者有一方赢了就break
同理,人机输入坐标后也是如此
(每次执行IsWin都会返回一个字符)
while (1) {
PlayerMove(board, ROW, COL);//玩家输入坐标
DisplayBoard(board, ROW, COL);//然后显示一边棋盘当前的情况
if (IsWin(board, ROW, COL) != 'C') {
break;
}
ComputerBoard(board, ROW, COL);//人机输入坐标
DisplayBoard(board, ROW, COL);//再显示一边棋盘当前的情况
if (IsWin(board, ROW, COL) != 'C') {
break;
}
}
注意:符号' C '说明没满并且没有一方赢
5.判赢
在while()循环出来后,肯定是有一方赢了或者满了
如果返回的符号为‘ * ’则玩家赢
如果返回的符号为‘ # ’则人机(电脑玩家)赢
如果返回的符号为‘ D ’则平局
具体可以看一下下文的IsWin函数具体实现,有注解
if (IsWin(board, ROW, COL) == '*') {
printf("玩家赢\n");
}
else if (IsWin(board, ROW, COL) == '#') {
printf("电脑玩家赢\n");
}
else if (IsWin(board, ROW, COL) == 'D') {
printf("平局\n");
}
2.game.c
(1)初始化棋盘(InitBoard)
void InitBoard(char board[ROW][COL], int row, int col) {
//InitBoard(board,ROW,COL);//初始化棋盘
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
board[i][j] = ' ';
}
}
/*或者直接写这一行代码也可以memset(&board[0][0], ' ', row * col * sizeof(board[0][0]));*/
}
(2)显示棋盘(DisplayBoard)
void DisplayBoard(char board[ROW][COL], int row, int col) {
//DisplayBoard(board, ROW, COL);//显示棋盘
for (int i = 0; i < row; i++) {
if (i < 2) {
printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
printf("---|---|---\n");
}
else {
printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
}
}
}
效果如图:
(3)玩家输入坐标(PlayerMove)
玩家的棋子是' * '号
void PlayerMove(char board[ROW][COL], int row, int col) {
//PlayerMove(board, ROW, COL);//玩家输入坐标
int x, y;
printf("玩家下棋:>\n");
printf("请输入棋子的坐标:");
scanf("%d %d", &x, &y);
while (1) {
if (x <= 0 && x >= 4 && y <= 0 && y >= 4) {
printf("坐标非法,请重新输入\n");
}
else if (board[x - 1][y - 1] == ' ') {
board[x - 1][y - 1] = '*';
break;
}
else {
printf("坐标已经被占用,请重新输入坐标\n");
break;
}
}
}
效果如图:
(4)人机下棋(ComputerBoard)
人机的棋子是' # '号
void ComputerBoard(char board[ROW][COL], int row, int col) {
//ComputerBoard(board, ROW, COL);//人机输入坐标
//DisplayBoard(board, ROW, COL);//然后显示一边棋盘当前的情况
printf("电脑下棋:>\n");
int x, y;
while (1) {
x = rand() % row;//模上一个3之后得到的数的范围肯定为0~2
y = rand() % col;
if (board[x][y] == ' ') {
board[x][y] = '#';
break;
}
}
}
效果如图:
可以看到我们在输入坐标后紧跟着人机也输入了坐标
(5)判定双方是否赢了(IsWin)
char IsWin(char board[ROW][COL], int row, int col) {
//IsWin(board, ROW, COL) 判定双方是否赢了
//判断行是否相等(注意不为空),相等的话就返回其对应的棋子,再下定论谁赢了
for (int i = 0; i < row; i++) {
if (board[i][0] == board[i][1] && board[i][1] == board[i][2]&&board[i][2]!=' ') {
return board[i][0];//返回
}
}
//判断列是否相等(注意不为空),相等的话就返回其对应的棋子,再下定论谁赢了
for (int j = 0; j < col; j++) {
if (board[0][j] == board[1][j] && board[1][j] == board[2][j] && board[2][j] != ' ') {
return board[0][j];//返回
}
}
//判断两对角线是否相等(注意不为空),相等的话就返回其对应的棋子,再下定论谁赢了
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != ' ') {
return board[0][0];//返回
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ') {
return board[0][2];//返回
}
//判断是否满了,返回不同的字符执行不同的效果
if (IsFull(board, ROW, COL)) {
return 'D';//返回
}
else {
return 'C';//返回
}
}
大致效果:
(6)判满(对应(5)中的函数IsFull())
注意该函数写在IsWin()函数的上边,否则加上声明
int IsFull(char board[ROW][COL], int row, int col) {
//IsFull(board, ROW, COL)判满
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] == ' ') {
return 0;//返回0说明没满,if(0)相当于false
}
}
}
return 1;//相当于true
}
一键三连哦,感谢大家的阅读!