C语言学习记录

今人不见古时月,今月曾经照古人,

现在是2025年7月31日,工作之余学习C语言的第98天,目前学习内容是操作符,

这两天有一个关于三子棋的小游戏项目,坦诚的说我是看过一次教程,才自己动手写的,所以最重要的主体框架是借鉴来的,当然自己写这四百多行代码的时候也是出现了很多的BUG,各种差错,比如变量名拼写错误,循环少写break,缺少判断胜负判定,if else 与 if 混淆导致判定结果出错,测试代码的时候总是能跳出我的“完美逻辑”,整出幺蛾子,由于我用的是宏定义的 行和列,那么后期优化为五子棋,十字棋都是很方便的,只要把输赢判断逻辑这个大工程处理好也不是不可以,下面就是我的三子棋游戏代码,

//game.h// 头文件名,声明函数,

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROW 3 // 宏定义,属于预处理指令,核心理解为文本替换,不进行类型校验,
#define COL 3

// 初始化棋盘 initboard
// 显示棋盘内容 displayboard
// 玩家下棋 playermove
// 电脑下棋 computermove // 找没有下棋的地方随机下棋,

// 初始化棋盘,
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);

// 判断输赢,
// 玩家赢,返回 ' * '
// 电脑赢,返回 ' # '
// 平局 返回 ' q '( quit )
// 胜负未分 返回 ' c '( continue )
char iswin(char board[ROW][COL], int row, int col);

// 判断棋盘是否下完,
// 棋盘下完返回 0
// 棋盘未下完返回 1
int full(char board[ROW][COL], int row, int col);

//logic.c// 源文件名,逻辑主体,

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

// 菜单显示,
void menu()
{
    printf("#####################################\n");
    printf("#############  1  play  #############\n");
    printf("#############  0  exit  #############\n");
    printf("#####################################\n");
}

// 游戏的实现,
void game(char board[ROW][COL],int row,int col)
{

    // 初始化棋盘,
    initboard(board,row,col);
    // 显示棋盘,
    displayboard(board,row,col);
    // 轮流下棋,
    while (1)
    {
        // 用于接收判断输赢的变量,
        int result = iswin(board, row, col);
        if (result == 'c')
        {
            playermove(board, row, col);
            displayboard(board, row, col);
            // 判断输赢,
            result=iswin(board, row, col);
            if (result == '*')
            {
                printf("铁汁,你赢了!\a\a\a\a\a\n");
                break;
            }
            computermove(board, row, col);
            displayboard(board, row, col);
            // 判断输赢,
            result=iswin(board, row, col);
            if (result == '#')
            {
                printf("还得练,\a\n");
                break;
            }
        }
        if (result == 'q')
        {
            printf("平局,旗鼓相当的对手!\a\n");
            break;
        }

    }

}

int main()
{
    srand((unsigned int)time(NULL));// 设置随机数的生成起点,
    char board[ROW][COL] = { 0 };
    int input = 0;
    do
    {
        menu();// 打印菜单,
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            printf(" 三子棋游戏( 规则; 先将三个棋子连成一线的获胜)\n 下棋示例:\n 第一格坐标:< 1 , 1 >\n 第二格坐标;< 1 , 2 >\n");
            game(board, ROW, COL);
            break;
        case 0:
            printf("退出游戏\n");
            break;
        default:
            printf("输入错误,请重新输入:\n");
            break;
        }
    } while (input);
    return 0;
}

//game.c// 源文件名,游戏实现,

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"


// 初始化棋盘,
void initboard(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 displayboard(char board[ROW][COL], int row, int col)
//{
//    for (int i = 0; i < row; i++)
//    {
//        // 打印数据,
//        printf(" %c | %c | %c \n",board[i][0],board[i][1],board[i][2]);// 太矬,
//        
//        // 打印分割行,
//        if (i < row - 1)
//        {
//            printf("___|___|___\n");
//        }
//    }
//    printf("   |   |   \n");
//}
void displayboard(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 j = 0; j < col; j++)
            {
                printf("___");
                if (j < col - 1)// 过滤掉最后一列 " | "
                {
                    printf("|");
                }
            }
            printf("\n");
        }
    }
    for (int 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("请输入坐标:<__,__>\n");
        scanf("%d %d", &x, &y);
        if (x>=0&&x<=row&&y>=0&&y<=3)
        {
            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;// 得到行下标范围 0 - 2
        y = rand() % col;// 得到列下标范围 0 - 2
        if (board[x][y] == ' ')
        {
            board[x][y] = '#';
            break;
        }
        break;// 第二次 BUG ,漏写一个 braak; 导致棋盘下满但无法输出平局信息,
    }
}

// 判断输赢,
char iswin(char board[ROW][COL], int row, int col)
{
    // 判断行,
    for (int 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];// 此处为了确保唯一性,所以不能返回 board[i][0], 与满足对角线情况重复,
        }
    }
    // 判断列,
    for (int j = 0; j < col; j++)
    {
        if (board[0][j] == board[1][j] && board[2][j] == board[1][j] && board[1][j] != ' ')
        {
            return board[1][j];// 此处为了确保唯一性,所以不能返回 board[0][j], 与满足对角线情况重复,
        }
    }
    // 判断对角线,
    if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
    {
        return board[1][1];
    }
    if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' ')
    {
        return board[1][1];
    }
    // 平局,
    if (full(board, row, col))
    {
        return 'c';
    }
    else// 第一次出现 BUG 就是这里,少写 else 导致无法再次回到 game() 中的 while(1) 循环,
    {
        return 'q';
    }
}

// 判断棋盘是否下完,棋盘没下完返回 1  ,棋盘下完返回 0 
int full(char board[ROW][COL], int row, int col)
{
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (board[i][j] ==' ')
            {
                return 1;
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值