coding game, 邊打遊戲邊學編程,是一種怎麼樣的體驗?

  • 2021 年 11 月 11 日
  • 筆記

前言

hello,大家好,我是bigsai,好久不見,甚是想念!

在日常生活中,很多人喜歡玩遊戲,因為遊戲中有著對抗博弈、控制的喜悅,用靈魂指法完成一波靚麗的操作。

但實際上,你的按鍵都是對應程式碼中一個個方法函數去執行操作,並且介面做到一個圖形變化渲染讓你感覺你控制的是這個圖形介面。

雖然遊戲的底層都是一行行程式碼堆砌的邏輯,但是我們對其並沒有半點興趣因為寫程式碼的過程枯燥無趣,完全需要腦子去抽象出一個頁面、執行邏輯,出錯的時候有很簡單的找了半天…… 輸出、debug各種方式去找問題。

對於咱們這種懶人來說,想要鍛煉自己編程能力、演算法真的是進入一種畏難的無限死循環,希望要麼簡單點、要麼有趣點,寫的東西最好也能像有些開發那樣看得見,摸得著,學習別那麼難。

這不,今天就發現了一個非常適合初、中級學者鍛煉自己編程的網站:codingame一個邊玩遊戲邊學編程的網站

網站主頁為://www.codingame.com/start

網站介紹

我們在學習技術、學習演算法的時候,都喜歡看一些圖將抽象內容具體化,甚至是如果有一些動圖如果能夠模擬一下程式執行邏輯之類的那就更受歡迎了,但是往往這類內容涉及到的底層非常多,並且優質的內容非常稀疏,但我今天推薦的這個網站真的是挺讓人驚喜的,網站進入的第一感覺就是:卧槽,這是小霸王嘛? 啥玩意啊。

一些小遊戲動畫切換背景,看著codingame這個url你絲毫不會想到這個網站跟編程有啥任何關係,只會想到:

  • 這到底是個啥?
  • Google翻譯一下看看……

註冊個帳號登錄之後才能顯示更多的內容,仔細看下背景右側還是有一些程式碼的,還是有一些非常神秘的感覺。

image-20211103000352257

登錄之後,左上角的practice可以進行一些練習,頁面會有各種難度的遊戲問題,這些問題都有一個小的遊戲背景、規則、考察點等待你去完成,比如easy難度的大部分都是字元串、哈希、循環控制這類問題,而mid難度的考察點更廣泛比如很多二分查找、bfs、圖論等等,如果英文不好可以藉助翻譯中英對比著看(狗頭🐶舉手),對於hard難度的有興趣可以自行挑戰。

image-20211103233203028

對於這裡面的問題,有的是文本形式的,但是更多的是小遊戲方式有動畫更加直觀。

還有一個非常重要的是,它支援多種程式語言,不管你是那種主流語言的愛好者,都可以暢想邊玩遊戲邊學編程的快樂。

easy初體驗:ASCII的藝術

這裡和大家一起體驗一下easy題怎麼玩,我首先點進去的是一個叫ASCII Art的題.

地址為://www.codingame.com/ide/puzzle/ascii-art

剛進來就是一種黑色科技感十足,讀完題可能有些小夥伴很懵逼,這是啥玩意,這個程式又跟我們平常見得有點不一樣,不需要像力扣那樣完成整個方法,也不是和acm那種提交整個可執行程式碼提交,這個程式它會事先聲明好一些內容你只需要在它提示的地方寫對應邏輯的程式碼就可以了,並且所有的結果要列印出來。

但是細心的小夥伴會發現這個其實就是和我們日常的刷題很像很像,不就換個樣子嘛,沒啥不一樣的。

image-20211103235700708

而這題的題意也很簡單,我口述一下(可能不標準):

給機場你經常看到這個牛批的顯示器:(圖片)

你有沒有問過自己,在一個好的舊終端上怎麼顯示這個數字?(我怎麼會難為我自己呢),我們有:用ASCII藝術

ASCII 藝術允許您使用字元來表示。 準確地說,在我們的例子中,這些形式是詞。 例如,單詞「MANHATTAN」可以在 ASCII 藝術中顯示如下:

image-20211104000420895

這個就有點似曾相識了,我也曾列印過大的0-9……

在看輸入輸出和其他要求

輸入

第 1 行:寬度L以 ASCII 藝術表示的字母。所有字母的寬度相同。

第 2 行:高度H以 ASCII 藝術表示的字母。所有字母的高度相同。

第 3行:待輸出的文本T,有n個ASCII字元組成。

後面幾行:字元串 ABCDEFGHIJKLMNOPQRSTUVWXYZ? 以 ASCII 藝術字(輸出到螢幕結果)表示。

輸出

文本 T在 ASCII 藝術中。
字元 a 到 z 在 ASCII 藝術中顯示為大寫的等效字元。
不在區間 [az] 或 [AZ] 中的字元將在 ASCII 藝術中顯示為問號。

問題分析:

這雖然是個簡單的問題,但是怎麼分析呢?

對於給定的寬度L,和高度H,其實就是限定了每個字元在控制台的大小,這個如何理解呢,舉個例子你就能明白。對於0來說,不同寬高的0可能長得樣子不一樣滴:

# # #   # # #   # # # #
#   #   #   #   #     #
# # #   #   #   #     #
        #   #   #     #
        # # #   # # # #

3*3     3*5      4*5
圓潤型   瘦長型    標準型

其實也就是限定寬高每個字元你可以迅速鎖定它的位置,存儲方面不用多想肯定是個二維的存儲(多個一維或者二維)。

在輸出的時候,根據字元計算 對應的位置,對應輸出就可以了,考慮到一些小白玩家還是可能不太明白,我貼上自己的🌶🐔程式碼,僅供參考:

import java.util.*;
import java.io.*;
import java.math.*;

/**
 * Auto-generated code below aims at helping you parse
 * the standard input according to the problem statement.
 **/
class Solution {

    public static void main(String args[]) {
        Scanner in = new Scanner(System.in);
        int L = in.nextInt();//寬
        int H = in.nextInt();//高
        char ch[][]=new char[H][L];
        if (in.hasNextLine()) {
            in.nextLine();
        }
        String T = in.nextLine().toUpperCase();
        for (int i = 0; i < H; i++) {
            String ROW = in.nextLine();//輸入每一行
            ch[i]=ROW.toCharArray();//賦值給對應行
        }
        char value[][]=new char[H][T.length()*L];
        for(int i=0;i<T.length();i++){
            char temp=T.charAt(i);
            int index=temp-'A';
            if(index<0||index>26)
                index=26;//不是字母統統問號 ???
            
            for(int j=0;j<H;j++){
                
                for(int q=0;q<L;q++)
                {
                    value[j][q+i*L]=ch[j][q+L*index];//賦值給待輸出結果
                }
            }
        }
        for(char tem[]:value){
            for(char temp:tem){
                System.out.print(temp);
            }
            System.out.println();
        }

        // Write an answer using System.out.println()
        // To debug: System.err.println("Debug messages...");

        //System.out.println("answer");
    }
}

20211104125804

測試完提交即可。

mid初體驗二分

看完一個easy題,你可能覺得好像也沒啥哈,那行,咱們一起看個經典的mid題:

鏈接為://www.codingame.com/ide/puzzle/shadows-of-the-knight-episode-1

image-20211104141808736

這個題具體要求大家可以自行到上面看看,但是大概的意思就是:

告訴你你在的區域長寬告訴你你的初始點

你的目標是最終走到某個終點,不告訴你具體坐標,只告訴你目標點在你當前點的方位(有八個方向)。你需要在N步之內走到目標節點位置上,每走一輪你都要輸出你當前點的位置。

看到這個問題還沒讀太懂的時候,上去就寫了個每次只走一步的程式碼,結果遇到一個非常長的地圖結構那就GG了。

後來想了一下,告訴方位我們可以每次進行二分查找,並且壓縮所在區域的位置啊,也就是

遇到所有U方位的:說明地圖最底部在這個點之上

遇到所有D方位的:說明地圖最頂部在這個點之下

遇到所有L方位的:說明地圖最右側在這個點左面

遇到所有R方位的:說明地圖最左部在這個點有點

通過使用二分,將以前的O(n)時間複雜度降到O(logn)級別,基本上可以找到所有點了。

個人的程式碼可以給大傢伙一個小參考:

import java.util.*;
import java.io.*;
import java.math.*;

/**
 * Auto-generated code below aims at helping you parse
 * the standard input according to the problem statement.
 **/
class Player {

    public static void main(String args[]) {
        Scanner in = new Scanner(System.in);
        int W = in.nextInt(); // width of the building.
        int H = in.nextInt(); // height of the building.
        int N = in.nextInt(); // maximum number of turns before game over.
        int X0 = in.nextInt();
        int Y0 = in.nextInt();
        int u=0,d=H,l=0,r=W;

        // game loop
        while (true) {
            String bombDir = in.next(); // the direction of the bombs from batman's current location (U, UR, R, DR, D, DL, L or UL)

            // Write an action using System.out.println()
            // To debug: System.err.println("Debug messages...");
           if(bombDir.contains("U")){
                d=Y0;
                Y0=((u+Y0)/2);
            }
            if(bombDir.contains("D")){
                u=Y0+1;
                Y0=((d+Y0)/2);
            }
            if(bombDir.contains("L")){
                r=X0;
                X0=((l+X0)/2);
            }

            if(bombDir.contains("R")){
                l=X0;
                X0=((r+X0)/2);
            }

            // the location of the next window Batman should jump to.
            System.out.println(X0+" "+Y0);
        }
    }
}

查看測試案例結果為:

20211104142645

當然,對於每一個測試案例,你可以滾動滑看其中的測試中間每一輪對應的動畫,還是相當nice的。

image-20211104143011026

這樣自己寫的程式碼能夠可視化的看到每一步驟運行在影像上的結果,就像打怪升級一樣,有點意思。

總結

對於這麼一個網站,對初學者編程興趣的激發還是挺友好的,推薦三兩隊友一起打怪升級,也可舍友相互比拼,把這個題丟到寢室群里讓大夥一塊看看,看誰先做對。

不過任何一個工具都要挑著選著用,可以找一些有挑戰但自己可以接受的問題去嘗試。玩玩體驗一下還是挺有趣的!

個人公眾號:bigsai 歡迎關注