Giter Club home page Giter Club logo

cgame's People

Contributors

floatwoozy avatar rainbowroad1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cgame's Issues

有bug

在俄罗斯方块的项目中方块下落时会有残影停留

关于代码的一些问题

有幸在B站上看见了UP的视频,很感兴趣,简单地看了一下repo。
本身也是C语言开发者,目前是在做OS相关的学习和工作。因为很喜欢也经常使用C语言,所以对于代码中的很多问题不吐不快,还望UP见谅。

首先,想说的是,UP这样简单地根据代码行数(或字符数)的多少来评定代码是否精简的做法是完全错误的。并不是说想办法精简自己的代码,想方设法地把代码变得更简洁是错误的。而是说,代码是否精简与行数/字符数是没有必然联系的。因为编译器其实根本不在乎这个问题。编译器不会在乎代码是通过多少行完成的,只要是使用同样逻辑的代码,不管UP怎么消减行数,最终所编译出来可执行文件几乎都是一样的(可能根据编译器的优化策略会有细小差距)。这样就更不存在什么代码精简与否的问题了。

更糟糕的是,这样的代码会带来诸多问题。代码的可读性首当其冲,在这样的代码压缩下,不仅其他读者看不懂代码,UP自己过几个月之后再来阅读代码也会毫无疑问会很费劲。但可读性的问题都还不是最严重的。为了压缩代码而在代码中使用的各种各样的所谓“*操作”使得代码的健壮性根本无从谈起。

不妨结合实际的代码来做一个分析,我这里选用的是GluttonousSnake/1_tiny_14lines.c

1   #include <stdlib.h>
2   #include <conio.h>
3   int main() {
4       int W = 20, S = W * W, *m, z[2] = {0}, l = 3, i, c = 'D', C, *p, f;
5       for (srand(m = calloc(S, 4)), C = m[1] = -1; C - 27; _sleep(100)) {
6           if (_kbhit())C = _getch() & 95, C - 65 && C - 68 &&
7               C - 83 && C - 87 || (C ^ c) & 20 ^ 4 && (c = C);
8           p = z + !!(c & 2), *p += c / 3 & 2, *p = (--*p + W) % W;
9           f = !system("cls"), *(p = m + *z + z[1] * W) > 0 && (C = 27);
10          for (; *p && (m[i = rand() % S] || (--m[i], ++l, --f)););
11          for (i = 0, *p = l; i < S; ++i % W || _cputs("|\n"))
12              _cputs(m[i] > 0 ? m[i] -= f, "()" : m[i] ? "00" : "  ");
13    }
14 }
  1. 在同一行声明多个不同类型、不同含义的变量,且变量的命名不规范(Line 4)
    通常来说,无论是局部变量也好,还是全局变量也好,都最好是根据变量的含义分多行进行声明和初始化。这样做的好处是能够增加代码的可读性。考虑下面这段代码:
int cnt, sum, i, arr[5];

诚然,这样的代码也是能容易读懂的,但如果我们改成下面这样:

int cnt;     // counter for the iteration 
int sum;   // total sum of input 
int i;         // iteration var 
int arr[5];

通过分行声明,我们能够在变量后面加入适当的注释,使得他人能够更容易地读懂我们的代码。
另一个方面,对变量使用恰当/规范的命名也能增强代码的可读性与可维护性(通常来说,拥有良好的可读性往往意味着良好的可维护性)。在C语言以及大多数的编程语言中,惯用的命名法有蛇形命名法和驼峰命名法。UP感兴趣的话可以去了解一下。btw,全大写的变量名(更为严谨的说法应该是Identifier,标识符)往往代表常量,变量是不不应该使用全大写的。

  1. 对于calloc这样的内存管理函数的错误运用(Line 5)
    内存管理是C语言中的问题高发区,同时也是开销大户(从OS的层面来说callocmalloc这样的函数属于syscall的范畴,会需要调用对应的syscall handler函数,带来大量的时间开销)。那么考虑一个问题,在什么情况下,我们应该使用这样的内存分配函数?答案是当我们需要一段无法确定长度的内存空间时,即当我们需要动态地使用内存空间时。而显然这里并不属于这种情况。如果只是要求一段定长的数组,简单地使用数组就可以了。还有一个问题的代码中缺少对应的free语句来释放内存。诚然在进程(Process)结束时OS会释放掉这些内存,但是养成手动释放内存的习惯将能够更好地避免内存泄漏问题(这在程序的规模变大的时候会显得很致命)。

  2. 滥用逗号运算符
    代码中不少的连续运算操作都使用了,用于连接两个连续的表达式。尽管因为,运算符有着最低的优先级而使得大多数情况下这样的写法是没有问题的。但是,为什么不直接使用;呢?希望的功能是完全一样的,而且也绝对不会出现问题。

  3. 慎用可能引起副作用的操作符(自增、自减等操作)
    这些操作通常会带来副作用,所以尽量不要在比较长且复杂的表达式中使用这些操作符。

  4. 缺失的return 0;
    对于现代的大多数编译器来说这并不是什么问题,有些编译器会在编译时自动补全这样的缺省,但我们并不能保证也不应该指望编译器总会这样做。但从更好的代码风格的角度考虑,尤其是main函数实际上是要求返回一个int型变量的,最好是不要落下这句return 0;。UP感兴趣的话也可以去查一查main()函数返回值到底意味着什么。

代码的问题其实很多,限于篇幅先只写这么多。说实话,并不是想打击UP学习编程的积极性。而是我相信一些建议能够帮助UP写出更好的代码。在写代码时,绝不是说代码越简短越好。代码是给人看的,代码的可读性才应该是程序员首要考虑的东西之一(当然性能也很重要,但好的性能往往由算法这样的更上层的因素或是ABI这样的底层因素决定,而不是代码的长短),在实际的工作中有时甚至会牺牲些许性能来保证代码的可读性。

当然,我很认同UP尽可能精简自己代码的想法与努力。但我想,这个方向可能不是正确的。如果UP真的希望能够提高自己代码的性能并精简整个代码逻辑的话,不妨试试从算法/数据结构的角度着手。我个人比较推荐的是Mark Allen Weiss所著的《数据结构与算法分析(C语言描述)》(Data Structures and Algorithm Analysis in C);当然,如果UP尚有余力的话,可以去看看富有盛名的CSAPP(Computer Systems: A Programmer's Perspective),这些书会帮助你更好地理解“编程”这一行为,并写出更好的代码。

最后送UP一句话,也是我很喜欢的一句话:“真理总是美的,而美总是简单的。”在此谨祝UP学业顺利。

3_color_25lines.c的报错

3_color_25lines.c第12行
SetConsoleCursorInfo(GetStdHandle((DWORD)-11), &(CONSOLE_CURSOR_INFO){1});报错

扫雷Linux版无法运行

我在复制了扫雷Linux版的源代码后,我用gcc编译时,没有办法正常编译,会提示出错。
即使可以编译好,但也无法正常运行。


  • 我的电脑装的Linux是Ubuntu

  • 终端编译时的提示:
new.c: In function ‘set’:
new.c:14:13: warning: passing argument 1 of ‘srand’ makes integer from pointer without a cast [-Wint-conversion]
   14 |  for (srand(m), f = tmp; c++ < B; dig(j % W, j / W), m[j] = 16, k[j]--)
      |             ^
      |             |
      |             int *
In file included from new.c:3:
/usr/include/stdlib.h:455:33: note: expected ‘unsigned int’ but argument is of type ‘int *’
  455 | extern void srand (unsigned int __seed) __THROW;
      |                    ~~~~~~~~~~~~~^~~~~~
new.c:14:19: warning: assignment to ‘int (*)(int,  int)’ from incompatible pointer type ‘void (*)(int,  int)’ [-Wincompatible-pointer-types]
   14 |  for (srand(m), f = tmp; c++ < B; dig(j % W, j / W), m[j] = 16, k[j]--)
      |                   ^
new.c:16:4: warning: assignment to ‘int (*)(int,  int)’ from incompatible pointer type ‘void (*)(int,  int)’ [-Wincompatible-pointer-types]
   16 |  f = dig, s += B, dig(x, y);
      |    ^
new.c: In function ‘main’:
new.c:22:9: warning: assignment to ‘int (*)(int,  int)’ from incompatible pointer type ‘void (*)(int,  int)’ [-Wincompatible-pointer-types]
   22 |  for (f = set, s = W * H, m = calloc(s * 2, 4), k = m + s; c - 27; j = 0) {
      |         ^
new.c:29:15: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘long int’ [-Wformat=]
   29 |  printf("%s! %ds", j ? "you win" : "Game over", clock() / CLOCKS_PER_SEC);
      |              ~^
      |               |
      |               int
      |              %ld

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.