有了分支、循环、函数、数组的一些知识后就能实现简单的小游戏的实例比如三子棋;为了避免主函数臃肿,用到很多自定义函数,以及两个项目一个自定义头文件,以至于主函数只有这么点(笑)。
话不多说,上码;
首先是main函数所在的项目
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"//包含自建头文件
void menu()
{
printf("***************************************\n");
printf("********* 三子棋 *********\n");
printf("********* 1. play *********\n");
printf("********* 0. exit *********\n");
printf("***************************************\n");
}
void game()
{
char judge = 0;
char board[ROW][COL];//棋盘
init_board(board, ROW, COL);//调用函数初始化棋盘(数组)全为空格
print_board(board, ROW, COL);//打印棋盘
while (1)
{
player_turn(board, ROW, COL);//玩家落子
print_board(board, ROW, COL);
judge = is_win(board, ROW, COL);//判断游戏状况
if (judge != 'c')//返回值有c、e、*、#
{ //c(继续),e(结束)
break; //*(玩家胜),#(电脑胜)
} //这么笨的电脑不会真会输8(bushi)
pc_turn(board, ROW, COL);//电脑下棋
print_board(board, ROW, COL);//再次打印棋盘
judge = is_win(board, ROW, COL);
if (judge != 'c')
{
break;
}
}
if (judge == '*')//判断跳出循环后的情况
printf("你赢了捏\n");
else if (judge == '#')
printf("逊!\n");
else if (judge == 'e')
{
printf("平局捏\n");
}
}
void test()
{ //空指针(NULL),让time()返回当前时间
srand((unsigned int)time(NULL));//unsigned int转换返回格式避免警告
int input = 0;
do
{
menu();
printf("是否开始游戏1(Y),0(N):\n");
scanf("%d", &input);//输入input
switch (input)
{
case 1:
printf("游戏开始了喵\n");
game();//调用game函数即进入游戏
break;
case 0:
printf("已退出喵\n");
break;
default:
printf("请输入1或0喵\n");
break;
}
} while (input);//0为假非0为真,1和0的设计便于继续选择和结束
}
int main()//主函数尽量内容不多
{
test();//调用test函数
return 0;
}
接着是自建头文件和另一个项目
#pragma once
//在自建头文件中包含了其他头文件在包含了自建头文件的源文件中就不用再包含
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define COL 3//列
#define ROW 3//行 定义全局变量便于后续修改
//声明
void init_board(char board[ROW][COL], int row, int col);//初始化
void print_board(char board[ROW][COL], int row, int col);//打印
void player_turn(char board[ROW][COL], int row, int col);//玩家回合
void pc_turn(char board[ROW][COL], int row, int col);//电脑回合
char is_win(char board[ROW][COL], int row, int col);//判断输赢
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
static void Init(int* count, int* count1, int* count2)
{
*count = 0;
*count1 = 0;
*count2 = 0;
}
void init_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
board[i][j] = ' ';
}
}
}
void print_board(char board[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)//棋盘 | | ,
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
if (i < row - 1)//始终要比棋盘行少一行
{
for (int k = 0; k < row; k++)//棋盘--- --- ---
{
printf("---");
printf(" ");
}
}
printf("\n");
}
}
void player_turn(char board[ROW][COL], int row, int col)
{
int r = 0;//输入的行
int c = 0;//输入的列
printf("player turn:\n");
while (1)//写1是死循环,但是满足条件直接可以跳出
{
printf("sample: 1 1 ==>1st row,1st col\n");
printf(" 1<=r<=%d 1<=y<=%d\n", row, col);
scanf("%d %d", &r, &c);
if (r >= 1 && r <= row && c >= 1 && c <= col)
{
if (board[r - 1][c - 1] == ' ')
{
board[r - 1][c - 1] = '*';//输入坐标-1,因为数组下标从0开始
break;
}
else
{
printf("该位置被占了捏,请换个位置喵\n");
}
}
else
{
printf("请按规定输入喵\n");
}
}
}
void pc_turn(char board[ROW][COL], int row, int col)
{
printf("pc turn:\n");
while (1)
{
int r = rand() % row;//通过rand()生成随机数
int c = rand() % col;//通过%row或%col来得到范围内的数
if (board[r][c] == ' ')//判断随机坐标是否被占用,被占用就进入循环
{
board[r][c] = '#';
break;
}
}
}
char is_win(char board[ROW][COL], int row, int col)
{
int count = 0;
int count1 = 0;
int count2 = 0;
int i = 0;
int j = 0;
for(i = 0; i < row; i++)//for循环判断行是否有满三个的
{
for(j = 0; j < col; j++)
{
if (board[i][j] == '*')
{
count1++;
}
if (board[i][j] == '#')
{
count2++;
}
count++;
}
if (count == row && count1 == row)
{
return '*';
}
if (count == row && count2 == row)
{
return '#';
}
if (count == row && count1 != row && count2 != row)
{
Init(&count, &count1, &count2);
}
}
Init(&count, &count1, &count2);
for (i = 0; i < col; i++)//判断列是否满三个
{
for (j = 0; j < row; j++)
{
if (board[j][i] == '*')
{
count1++;
}
if (board[j][i] == '#')
{
count2++;
}
count++;
}
if (count == row && count1 == row)
{
return '*';
}
if (count == row && count2 == row)
{
return '#';
}
if (count == row && count1 != row && count2 != row)
{
Init(&count, &count1, &count2);
}
}
Init(&count, &count1, &count2);
for (i = 0,j = 0; i < row; i++)//判断左上到右下
{
if (board[i][j] == '*')
{
count1++;
}
if (board[i][j] == '#')
{
count2++;
}
count++;
j++;
if (count == row && count1 == row)
{
return '*';
}
if (count == row && count2 == row)
{
return '#';
}
if (count == row && count1 != row && count2 != row)
{
Init(&count, &count1, &count2);
}
}
Init(&count, &count1, &count2);
for (i = 0, j = col - 1; i < row; i++)//判断右上到左下
{
if (board[i][j] == '*')
{
count1++;
}
if (board[i][j] == '#')
{
count2++;
}
count++;
j--;
if (count == row && count1 == row)
{
return '*';
}
if (count == row && count2 == row)
{
return '#';
}
if (count == row && count1 != row && count2 != row)
{
Init(&count, &count1, &count2);
}
}
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] == ' ')
{
return 'c';
}
}
}
return 'e';
}
关于这个static,让这个Init函数变为静态,仅能在所在的.c项目中调用
也许就有人要问了,“啊,你写这么多循环干什么,反正都是三子棋了,直接全部改3不好,用循环不是白费劲?”
诶,问得好,假设这就是拿一堆常数写的三子棋,拿如果突然让你改成五子棋呢?
“这不简单?把常量改了不就好了。”
但是只需要稍微动动脑,定义两个全局变量,后面修改不就轻轻松松,虽然这个三子棋不会有人让你改成五子棋,但是需要有这一种思想,要把目光放长远些。
(写得可能不怎么好,特别是判断输赢那一块,太臃肿了,但是如果能对你有帮助是我莫大的荣幸)