中學時代的無聊作品(古董PASCAL數獨)
圆周率派2010/12/17软件综合 IP:香港
中學讀理科,電腦是選修課,考試題目是用PASCAL做數獨。
為什麼用古董PASCAL而不是C?這個問題要問老師。
完成於中學五年級(高中二年級)

我做的應該是全班最好的那個(功能最多)。
使用Free Pascal Editor編寫,MS-DOS界面運行。
本人現在讀大一,社會科學系。變得對電腦編程一竅不通。


我的遊戲在當初設計的時候,設定為以下幾個功能:

I)我的數獨遊戲的基本功能
提供多達二十條題目的題庫、選擇難度、時間計算、判斷正誤並且顯示不同顔色字體;

II)我的數獨遊戲的其他功能
計算分數,以語句顯示正誤、存儲功能等等;

III)其他
本數獨遊戲為標準遊戲玩法,即
9×9的格子中,用199個阿拉伯數字填滿整個格子,要求符合:
每一行都用到1,2,3,4,5,6,7,8,9,位置不限;
每一列都用到1,2,3,4,5,6,7,8,9,位置不限;
3×3的格子都用到1,2,3,4,5,6,7,8,9,位置不限;
題目提取方法為隨即提取,但範圍是在玩家所選定難度內;
時間計算對最終分數没有影響,(具體參見程式說明);
ESC退岀
該遊戲以MS-DOS繫統為平臺。

IV)該程式的優點及不足
該程序功能比較全面,並且有難度選擇,使玩家有較多選擇

然而由于時間倉卒以及限于作者的能力和知識水平有限,無法做到盡善盡美,而且程序祗能保證基本運算正常,無法與之岀現BUG(即程式錯誤)和偶然性程序『異變』的情況,現在已知Pascal所能造成的最壞情況為當機。
好,是時候講解一下我的成果了。
+10  科创币    caoyuan9642    2010/12/17 不需要每一句都解释。。不是所有人都只会C
来自:计算机科学 / 软件综合
6
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
圆周率派 作者
13年5个月前 IP:未同步
269557
數獨程式本體

Program Sudokugame;
Uses crt;
{Instruction
Second code    Meaning
0    Null(空)          
27    ESC                    
59-68    Keys F1-F10      
71    Home  
72    ↑
73    PgUp
75    ←
77    →
79    End
80    ↓
81    PgDn
82    Ins
83    Del}

本段為附加部分。
程式第一行,『Sudokugame』是本程式的名稱。
第二行,uses crt是Free pascal editor(以下簡稱FPE)每一個程式的開頭必須輸入的指令語句。與FPE所不同的是,Turbo Pascal(以下簡稱TP)的指令語句是uses wincrt。 在Pascal中有一個 CRT 單元及一個 GRAPH 單元,那麼什麼是CRT呢?簡單的說CRT 單元是為了實現字符的顯示與處理,另外的那個稱為 GRAPH 單元是專門用來處理圖形的。我們看到的有關圖形的程式往往都要用到。所以若是要在Pascal中實現圖形操作,就必須要調用 CRT 單元及GRAPH 單元。到目前為止,FPE的CRT的性能是所有的PASCAL之中最穩定的。
第三行至最後一行都是電腦的鍵盤輸入代碼,正式名稱為『ASCII碼』或『ASCII(American Standard Code for Information Interchange,美國資訊互換標準代碼)是基於拉丁字母的一套電腦編碼系統。它主要用于顯示現代英語和其他西歐語言。它是現今最通用的單字節編碼系統,並等同於國際標準ISO 646(注:部分轉載自維基百科)。它的實質是將鍵盤上的每一個鍵都轉換成電腦所能識別的符號或數字代碼,以供電腦讀取和接受指令。


Const
     left=20;
     up=3;
     SPACE = ' ';
     COL1 = LIGHTGRAY;
     COL2 = WHITE;
     COLBG = BLUE;
     COL3=YELLOW;

本段為程式的常量(Constant)部分。
第一行和第二行為遊戲佈局圖初始位置的指令,即從左往右數第二十個游標位,從上往下數第三個游標位為佈局圖的左上角第一個坐標的位置。
第三行,SPACE為常量定義字符,在本程式中的意義為無字符游標位(空格),在主程式中將有詳細說明。
的四行之第七行是程式的字符顏色定義。以後若出現等號前的定義字符,那麼接下來的需要顯示的文字將會變成此種顏色,除非有另外的說明。其中COLBG不是字符顏色定義,而是字體背景顏色,下文將作詳述。


Var I
     {'q' is short for question;'a' is short for answer}
     qeasy:Array [1..9,1..9] Of char;
     qmedium:Array [1..9,1..9] Of char;
     qhard:Array [1..9,1..9] Of char;
     aeasy:Array [1..9,1..9] Of char;

本段為變量(Variation)說明。由於版面的限制,故以Var I 和Var II區分,但在實際的程式編寫時並不允許這樣做。
第一行是附加說明,不影響程式的本體,今後若使用花括號,則裡面的文字均為附加說明,用于方便程式員閱讀。
第二行至第五行是陣列(Array)變量說明。在本程式中用於題目與答案的儲存和讀取。
二維陣列(Two-Dimentional Array)的一般格式是
XXX:Array[A..B,C..D] Of char(也可以是Longint、integer或real)
最左項的字符串是該變量的定義名稱。


Var II
amedium:Array [1..9,1..9] Of char;
     ahard:Array [1..9,1..9] Of char;
     qchall:Array [1..9,1..9] Of char;
     achall:Array [1..9,1..9] Of char;
     memory:Array[1..9,1..9] Of Boolean;
     save:Array[1..9,1..9] Of char;
     winner:Array[1..100] Of String;
     datafile:text;
     insFile:text;
     i,j,z:Integer;
     x,y:Integer;
     ch:char;
     mark:Integer;
     {'sec' is short for second;'min' is short for
     minute;'hr' is short for hour}
     sec,min,hr:Real;
     Name:String;
     press:char;
     content:String;

本段為變量說明第二部分。
第一至第七行同上,皆是陣列,但只有第一部分的第二至四行和第二部分的第一至四行是題目和答案的文本文檔儲存變量,其他的三個陣列分別是布爾值記憶陣列(用于記錄數獨遊戲的空格填數與否)、整數記憶陣列(作用同前者,但處理對象不同)和用戶姓名記憶陣列。這三個陣列將於下文予以詳細說明。
第八行和第九行是TEXT(文本文檔)的說明,也就是說該個變量用于儲存文本文檔的資訊。
第十行至第十一行是整數變量,將於下文予以詳解。
第十一行是輸入鍵的變量,通常以Readkey來為之賦值,十七行的功能與之相似。
第十二行的MARK是遊戲分數的變量說明,再下面兩行是附加說明。
第十五行是時間變量,分別是秒鐘、分鐘和小時。
下一行的NAME是用戶輸入姓名的變量,用于儲存用戶的資料。
最後一行是文本文檔的字符串變量說明,與第十七行的定義有聯繫。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
圆周率派作者
13年5个月前 IP:未同步
269558
Procedure writexy(x,y:Integer;beta:String);
Begin
     gotoxy(x,y);
     write(beta)
End;

本段為程式初始化指令,整個程式分為一個個子程式(Procedure)和主程式(Main Program)。每一個子程式以Procedure作開頭,以end作結,結尾用分號;而主程式則以句號作結尾。
Gotoxy(x,y)用于在某一特定位置顯示字句或圖案,x,y內的值可以為任意數,但要注意儘量不要超出螢幕範圍。
Write用于顯示字句,括號內的內容要以『‘’』包含,方可正常顯示,已定義的變量名稱除外。

{view the start}
Procedure start;
Begin
  gotoxy(20,6);
   WriteLn('111111111111111111111111111111111111111');
  gotoxy(20,7);
   WriteLn('110110110110111111111111011111101111111');
  gotoxy(20,8);
   WriteLn('111010101101111111111011011111101111111');
  gotoxy(20,9);
   WriteLn('110000000100000000111100111111101111111');
  gotoxy(20,10);
   WriteLn('111100011010111011111110011100000001111');
  gotoxy(20,11);
   WriteLn('111010101110111011111101101001101101111');
  gotoxy(20,12);
   WriteLn('110110110110111011111011100101101101111');
  gotoxy(20,13);
   WriteLn('111101011111011011111111001101101101111');
  gotoxy(20,14);
   WriteLn('100000000011011011111100101100000001111');
  gotoxy(20,15);
   WriteLn('111011011111100111111011101111101111111');
  gotoxy(20,16);
   WriteLn('111100111111010111111111101111101110111');
  gotoxy(20,17);
   WriteLn('111010011110111011111101011111000000011');
  gotoxy(20,18);
   WriteLn('110111101101111101111110111000001111011');
  gotoxy(20,19);
   WriteLn('111111111111111111111111111111111111111');
   Repeat
    Until KeyPressed;
  ClrScr
End;

本段為進入遊戲顯示第一版面的子程式。
每一行的0和1組成的字串已被gotoxy限定位置,隨著縱坐標數值的遞增,每一行的文字顯示完畢後都將自動移到下一行(橫坐標不變)。但若只用writeln的話,每一行文字顯示完後都將自動跳至下一行,但以橫坐標首格作開頭。
倒數第四和第五行的repeat…until是重複性指令。Keypressed是任意鍵輸入指令;
再下一行的Clrscr是Clear screen的縮寫,也就是清除螢幕上的任何文字和圖案,後四句連起來表達就是:『重複直到按下任意鍵,然後便清洗螢幕,結束』 。


{view the title first}
Procedure title;
Begin;    
  gotoxy(25,13);
    writeln('Welcome to the SuDoKu challenge!');
    TextColor(YELLOW);
    
    gotoxy(53,20);
    writeln('Designer  Jerry Crystal Yu');
    
    gotoxy(60,21);
    writeln('Beta3.3.4');

    gotoxy(60,22);
    writeln('2006.10.20');
    
    gotoxy(30,23);
    write('All rights reserved');
      readln;
    Repeat
    Until KeyPressed;
  ClrScr
End;

本段為進入遊戲的第二個版面。
該版面純粹顯示作者、版本和日期,當然還有歡迎辭。為了保證顯示正常,需要加一個readln。而第一行語句由於沒有說明文本顏色,因此呈白色;而第二行語句前加了一行TextColor(YELLOW),那麼改語句則為黃色,依此類推。


{Enter the user's name}
Procedure enter;
Begin
  gotoxy(25,13);
  TextColor(WHITE);
  write('[s:9]lease enter your name:');
  read(Name);
  gotoxy(25,15);
  TextColor(YELLOW);
  writeln('Have fun with the game!');
      readln;
    Repeat
     Until KeyPressed;
  ClrScr
End;

本段為進入遊戲第三個版面,該版面的功能是讓用戶鍵入姓名並顯示語句。
其中變量NAME用于記憶用戶姓名,在第一行語句前面使用WRITE,可以使游標不會在顯示完此字句後跳至下一行,以使用戶輸入姓名。在程式下一行加上read來讀取名字NAME    ,然後按下回車鍵即可關閉此版面。


{View the map}
Procedure mapview;
Begin
TextColor(COL1);
writexy(1,1,'Sudoku Challenge');
writexy(left,up,  '@=@=@==@=@==@=@=@==@=@');
writexy(left,up+1, '|   |   |   |   |   |   |   |   |   |');
writexy(left,up+2, '@---+---+---+---+---+---+---+---+---@');
writexy(left,up+3, '|   |   |   |   |   |   |   |   |   |');
writexy(left,up+4, '@---+---+---+---+---+---+---+---+---@');
writexy(left,up+5, '|   |   |   |   |   |   |   |   |   |');
writexy(left,up+6, '@---+---+---+---+---+---+---+---+---@');
writexy(left,up+7, '|   |   |   |   |   |   |   |   |   |');
writexy(left,up+8, '@---+---+---+---+---+---+---+---+---@');
writexy(left,up+9, '|   |   |   |   |   |   |   |   |   |');
writexy(left,up+10,'@---+---+---+---+---+---+---+---+---@');
writexy(left,up+11,'|   |   |   |   |   |   |   |   |   |');
writexy(left,up+12,'@---+---+---+---+---+---+---+---+---@');
writexy(left,up+13,'|   |   |   |   |   |   |   |   |   |');
writexy(left,up+14,'@---+---+---+---+---+---+---+---+---@');
writexy(left,up+15,'|   |   |   |   |   |   |   |   |   |');
writexy(left,up+16,'@---+---+---+---+---+---+---+---+---@');
writexy(left,up+17,'|   |   |   |   |   |   |   |   |   |');
writexy(left,up+18,'@=@=@=@==@=@=@==@=@=@');
writeln;
writeln;
writeln;
textColor(COL2);
     TextBackground(COLBG);
End;

此版面用于顯示數獨遊戲佈局圖。
由第五行起至倒數第七行為止為本子程式的本體部分。這裡與第一個版面的顯示方法略有不同,但最終效果是一樣的。由於一開始在常量部分已經限定了LEFT和UP的初始位置,因此只需再在這兩個常量後面加進數字,便可以逐行顯示所要顯示的文字了。這裡有一個保留字WRITEXY,直接便可以顯示所需顯示的字句,舉一個例子:在本段中,writexy(left,up+1)也可以寫成gotoxy(left,up+1);
[換行]writeln(••••••)。倒數第二行的TextBackground即背景顏色,它只會將文字的背景轉變成另外一種顏色,而不會改變文字本身。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
圆周率派作者
13年5个月前 IP:未同步
269559
{load the question datafile}
Procedure loadfile;
Begin;
     randomize;
     z:=Random(5)+1;
   Case ch Of
    '1':assign(datafile,'qeasy.txt');
    '2':assign(datafile,'qmedium.txt');
    '3':assign(datafile,'qhard.txt');
    '4':assign(datafile,'qchall.txt');
    '5':assign(insfile,'instr.txt')
   End;
    
Reset(datafile);
     For i:=1 To (z-1)*9 Do
      readln(datafile);
     For i:=1 To 9 Do
       Begin;
        For j:=1 To 9 Do
         Begin
          read(datafile,qeasy[j,i]);
          save[j,i]:=qeasy[j,i];
          writexy(j*4-2+left,i*2-1+up,qeasy[j,i])
         End;
         readln(datafile);
       End;
Close(datafile)
End;

本段為載入題庫之子程式。
RANDOMIZE意即隨機抽取(題目),這樣每一次抽取的題目不會重複。次行的語句意義為在五條題目中(每一個等級都有五條題目)隨即抽取一題。由於電腦會由第0行開始讀題,因此需要增補『+1』 ,以使電腦可以從第一行開始抽題。CASE OF用于多條件語句,其作用等同於IFTHEN; IFTHEN等等。ASSIGN是讀取的命令字符,屬於保留字,括號內的即文本文檔名稱。為了不使多層數據一起出現,需要加一項RESET()來重設螢幕內容。
下一行和再下三行都是限定抽取題目範圍的命令語句,隨後顯示隨即抽取的題目。『J,I』變量是佈局圖中每一個非空格的坐標,只有寫了這一行,程式才可以
將一條題目中的所有數據一一讀取。


{load the answer datafile}
Procedure loadanswer;
Begin;
     Assign(datafile,'aeasy.txt');
     reset(datafile);
     For i:=1 To (z-1)*9 Do
      readln(datafile);
     For i:=1 To 9 Do
        Begin;
           For j:=1 To 9 Do
            read(datafile,aeasy[j,i]);
            readln(datafile);
        End;
   Close(datafile)
End;

本段為讀取答案的部分。


{marks and conclusion}
Procedure calculation;        
Begin
If memory[x,y]=False
   Then
    Begin
     If ch=aeasy[x,y]
       Then Begin
             mark:=mark+10;
             memory[x,y]:=True;
             gotoxy(1,23);
             TextBackground(BLACK);
             textColor(Yellow);
             writeln('Exactly!Right answer                      ');  
             writeln('You got ',mark,' marks.                  ');
             { Program to demonstrate the TextColor function. }
             qeasy[x,y]:=ch          
            End    
       Else Begin
             memory[x,y]:=True;
             gotoxy(1,23);
             TextBackground(BLACK);      
             TextColor(WHITE);
             writeln('This is a wrong answer.');
            End;
    End
   Else Begin
         If ch<>aeasy[x,y]
          Then Begin
                textcolor(RED);
                gotoxy(1,23);      
                writeln('Wrong!                     ')
               End;
         If ch=aeasy[x,y]
          Then Begin                  
                gotoxy(1,23);
                TextColor(YELLOW);
                writeln('Right answer.            ');
              
writeln;
                qeasy[x,y]:=ch
               End;
        End;      
End;

本段為檢驗答案對於否的子程式。


{second input}
Procedure scd;
Begin
  For i:=1 To 9 Do
    For j:=1 To 9 Do
      memory[j,i]:=False
End;

本段為為布爾值賦值的子程式,與上一段相聯繫。


{quit}
Procedure quit;
Begin
    gotoxy(15,5);
    TextColor(GREEN);
    writeln('*==================================================*');
    gotoxy(15,6);
    writeln('|                                                  |');
    gotoxy(15,7);
    writeln('|                                                  |');
    gotoxy(15,8);
    TextColor(WHITE);
    writeln('|    Do you want to end the game?                  |');
    gotoxy(15,9);
    TextColor(GREEN);
    writeln('|                                                  |');
    gotoxy(15,10);
    TextColor(WHITE);
    writeln('|    Push the      button to select                |');
    gotoxy(15,10);
    TextColor(YELLOW);
    gotoxy(29,10);
    writeln('Y/N');
    gotoxy(15,11);
    TextColor(GREEN);
    writeln('|                                                  |');
    gotoxy(15,12);
    writeln('|                                                  |');
    gotoxy(15,13);
    writeln('|                                                  |');
    gotoxy(15,14);
    writeln('|                                                  |');
    gotoxy(15,15);
    writeln('|                                                  |');
    gotoxy(15,16);
    TextColor(WHITE);
    writeln('|     One sentense for everyday                    |');

gotoxy(15,17);
    writeln('|    "Think carefully before quiting the game."    |');
    gotoxy(15,18);
    TextColor(GREEN);
    writeln('|                                                  |');
    gotoxy(15,19);
    writeln('*==================================================*');
    press:=readkey;
     readln(press);
     writeln(press);
      If (press='Y') Or (press='y')
       Then Begin
             ClrScr;
              TextColor(YELLOW);
              gotoxy(29,13);    
              writeln('See you next time!');
              readln;
             Repeat
              Until KeyPressed;
             ClrScr
            End;
      If (press='N') Or (press='n')
       Then Begin
             ClrScr;
             mapview;
              For i:=1 To 9 Do
              For j:=1 To 9 Do
               writexy(j*4-2+left,i*2-1+up,save[j,i])
            End;
End;

本段為顯示退岀版面的子程式。


{main part}
Begin
  start;
  title;
  enter;
      
  gotoxy(25,10);
    writeln('Choose the difficulty');
  gotoxy(25,13);
    writeln('"1"-Easy   "2"-Medium');
  gotoxy(25,15);
   writeln('"3"-Hard   "4"-Challenger');
  gotoxy(25,17);
    writeln('"5"-Instruction');

  readln;
    Repeat
     Until KeyPressed;
  
  ch:=readkey;
    Case ch Of
     '1':assign(datafile,'qeasy.txt');
     '2':assign(datafile,'qmedium.txt');
     '3':assign(datafile,'qhard.txt');
     '4':assign(datafile,'qchall.txt');
     '5':Begin
          clrscr;
          GotoXY(1,1);
          assign(insfile,'instr.txt');
          reset(insfile);
          While Not eof(insfile) Do
           Begin    
             readln(insfile,content);
             writeln(content);
           End;
         Repeat;
         Until KeyPressed;
         ClrScr
      End;
    End;

ch:=ReadKey;
Begin  
   Window(20,1,50,30);
   mapview;
   loadfile;
   loadanswer;
   sec:=0;
   min:=0;
   hr:=0;

    x:=1;
    y:=1;
    mark:=0;  
    Repeat;
     Repeat;
       gotoxy(x*4-2+left,y*2-1+up);
       ch:=readkey;
       {only if..then sentense can be used}
       If (ch=#0) Then ch:=readkey;
       If (ch=#75) Then x:=x-1;
       If (ch=#77) Then x:=x+1;
       If (ch=#72) Then y:=y-1;
       If (ch=#80) Then y:=y+1;
        
       If (x<1) Then x:=9;
       If (x>9) Then x:=1;
       If (y<1) Then y:=9;
       If (y>9) Then y:=1;
       If (ch>='1') And (ch<='9') And (qeasy[x,y]=' ')
         Then Begin
           write(ch);
         save[x,y]:=ch;
                calculation;  
              End;  
  
  window(1,15,15,2);
  {Time counting}
  Begin

Repeat;
       Begin
          If sec>=60
            Then Begin
                 min:=min+1;
                 sec:=0
                End;
          If min>=60
           Then Begin
                 hr:=hr+1;
                 min:=0
          End;
      Delay(10); {Wait one second}
          gotoxy(60,5);
          sec:=sec+0.008;
           TextBackground(BLACK);
        TextColor(WHITE);
        writeln(hr:2:0,' hr ',min:2:0,' min ',sec:2:0,' sec');
        gotoxy(x*4-2+left,y*2-1+up)
       End;
      Until KeyPressed;
  End;
  {Ready to quit}
    Until ch=#27;

  quit;
  Until (press='Y') Or (press='y');
  readln
End;
End.

本段為主程式。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
圆周率派作者
13年5个月前 IP:未同步
269560
(全篇完)

後記:

數獨題目的載入方法比較愚蠢,不是自行編寫題目,而是預先編好題目,用.txt檔案保存,然後再用DOS載入。
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
y2k
13年5个月前 IP:未同步
269563
CIT program?還是As?
Kc遇到香港人比較少..
Hi下.
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
圆周率派作者
13年5个月前 IP:未同步
269592
回 5楼(y2k) 的帖子
CIT[s:120][s:120]
引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
上级专业
同级专业
文件下载
加载中...
{{errorInfo}}
{{downloadWarning}}
你在 {{downloadTime}} 下载过当前文件。
文件名称:{{resource.defaultFile.name}}
下载次数:{{resource.hits}}
上传用户:{{uploader.username}}
所需积分:{{costScores}},{{holdScores}}下载当前附件免费{{description}}
积分不足,去充值
文件已丢失

当前账号的附件下载数量限制如下:
时段 个数
{{f.startingTime}}点 - {{f.endTime}}点 {{f.fileCount}}
视频暂不能访问,请登录试试
仅供内部学术交流或培训使用,请先保存到本地。本内容不代表科创观点,未经原作者同意,请勿转载。
音频暂不能访问,请登录试试
支持的图片格式:jpg, jpeg, png
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}