Gioco Frogger-ish


13

Che ne dici di dare al buon vecchio gioco arcade Frogger un risveglio, in stile Code Golf!

Il tuo compito è creare una versione di questo gioco classico, con il minor numero di caratteri di codice possibile. Usa la lingua che preferisci (sono consentite librerie come jQuery ecc.).

Requisiti

  • Hai 3 vite e perdi 1 vita da:
    • muoversi fuori dalla scena di gioco.
    • essere colpito da un vehice.
    • saltando in acqua.
    • saltando in una casa già occupata.
    • a corto di tempo.
  • La rana si muove con i tasti freccia.
  • C'è un bug "teletrasporto" con intervalli prestabiliti tra le cinque case (gli spazi tra l'erba in alto).
  • Ottieni 10 punti quando fai un passo avanti, 200 punti bonus quando catturi un insetto e 500 punti quando raggiungi una casa vuota.
  • Un timer si abbassa, più velocemente ogni livello (i veicoli, le rane e i tronchi dovrebbero muoversi più velocemente anche di ogni livello).
  • Dovrebbero esserci 5 corsie di veicoli e 3 corsie con tronchi e 2 con tartarughe.
  • Ogni corsia dovrebbe muoversi a una velocità scelta a caso (entro limiti ragionevoli).
  • Quando una casa disponibile viene occupata, una rana appare nel punto di partenza e tu controlli quella da quel punto.
  • Quando tutte e cinque le case sono state occupate, il timer si riavvia e le case si svuotano. Al termine del gioco, vengono calcolati e mostrati i punti di tutti i livelli.

informazioni addizionali

Schermata iniziale, musica e tabella dei punteggi migliori non sono necessari. Inoltre, non è necessario imitare il design sul pixel. Lo vuoi in bianco e nero? Lo vuoi davvero minimalista? O un cubo invece di una rana o una macchina? Funziona bene! Tieni il codice stretto. Il codice più corto vince!

inserisci qui la descrizione dell'immagine


I commenti sono stati eliminati perché erano obsoleti. Si prega di avvisare di eventuali informazioni perse che potrebbero essere state nei commenti eliminati.
Maniglia della porta

Risposte:


3

Python 3.3 - Ungolfed

Non l'ho mai giocato a golf, dato che ero più interessato a far funzionare prima un gioco bello. In realtà sono totalmente nuovo in Tk, quindi se qualcuno ha qualche suggerimento, li apprezzerei davvero. Le velocità ora funzionano correttamente. Fammi sapere se desideri vedere funzionalità aggiuntive, ad esempio i colori.

Codice

import tkinter as tk
import queue
import random    

class Lane():
 def __init__(self, row=-1, lanetype="none", direction=0, speed=0, width=0, maxnumber=0, replenish=0, length=0, gap=0):
  self.row = row
  self.type = lanetype
  self.direction = direction
  self.speed = speed
  self.width = width
  self.maxnumber = maxnumber
  self.replenish = replenish
  self.length = length
  self.gap = gap
  self.lanelastupdate = 0
  self.objects = []
  if(self.type == "car"):
   for index in range(self.width):
    if(len(self.objects) == self.maxnumber):
     break
    if((self.maxnumber - len(self.objects) == self.width - index) or random.random() < self.maxnumber/self.width):
     self.objects.append([index*self.direction + int((self.width-1)/2 - (self.width-1)*self.direction/2), self.row])
  if(self.type == "log" or self.type == "turtle"):
   if(self.direction == 1):
    start = 0
   else:
    start = self.width - 1
   lengthcounter = 0
   gapcounter = 0
   for index in range(self.width):
    if(lengthcounter < self.length):
     self.objects.append([start + index*self.direction, self.row])
     lengthcounter += 1
    else:
     gapcounter += 1
     if(gapcounter == self.gap):
      lengthcounter = 0
      gapcounter = 0
 ### end of __init__ ###
### end of Lane class ###

class Frogger():
 def __init__(self):
  # configure 'global' variables
  self.directions = ['Up', 'Down', 'Left', 'Right']
  self.width = 25
  self.height = 13
  self.frogstart = [12, 12]
  self.pointsforup = 10
  self.pointsforhome = 500
  self.pointsforbug = 200
  self.timerthreshold = 1000
  self.timerstart = 60
  self.speedchange = 2
  self.waterbordertop = 1
  self.waterborderbottom = 5
  self.minspeed = 10
  self.maxspeed = 15
  self.minbugspeed = 50
  self.maxbugspeed = 100
  self.timerspeed = 20    

  # configure program state variables
  self.q = queue.Queue(maxsize=1)
  self.updateticks = 0

  # configure game variables
  self.gameover = False
  self.speedup = 0
  self.timer = self.timerstart
  self.lives = 3
  self.score = 0
  self.frogposition = [0, 0]
  self.frogposition[0] = self.frogstart[0]
  self.frogposition[1] = self.frogstart[1]
  self.highest = 12
  self.movedup = False

  # configure the lanes of cars, logs, and turtles
  self.init_lanes()

  # configure the homes and the bug
  self.init_special()

  # configure TK window
  self.root = tk.Tk()
  self.label = tk.Label(text="Score: "+str(self.score)+" Lives: "+str(self.lives)+" Time: "+str(self.timer))
  self.label.pack()
  self.text = tk.Text(self.root, width=self.width, height=self.height, font=("Courier New", 14))
  self.text.bind("<Key>", self.key_event)
  self.text.focus_set()
  self.text.pack()

  # configure drawing sprites
  self.init_sprites()

  # run the game
  self.update_clock()
  self.process_world()
  self.root.mainloop()
 ### end of init ###

 def init_sprites(self):
  self.symbols = {"frog":chr(0x238), "rightcar":chr(187), "leftcar":chr(171), "turtle":chr(920), "log":chr(685), "bug":chr(1217), "grass":chr(993), "freehome":chr(164), "fullhome":"@", "road":"-", "water":chr(0x2248), "saferow":"*"}
  self.sprites = {value:key for key, value in self.symbols.items()}
  self.text.tag_configure("frog", foreground="chartreuse", background="dark green")
  self.text.tag_configure("rightcar", foreground="yellow", background="black")
  self.text.tag_configure("leftcar", foreground="yellow", background="black")
  self.text.tag_configure("turtle", foreground="orange red", background="cyan")
  self.text.tag_configure("log", foreground="sienna", background="cyan")
  self.text.tag_configure("bug", foreground="maroon", background="green")
  self.text.tag_configure("grass", foreground="orange", background="green")
  self.text.tag_configure("freehome", foreground="forest green", background="green")
  self.text.tag_configure("fullhome", foreground="red", background="green")
  self.text.tag_configure("road", foreground="gray", background="black")
  self.text.tag_configure("water", foreground="navy", background="cyan")
  self.text.tag_configure("saferow", foreground="pink", background="black")
 ### end of init_sprites ###

 def update_clock(self):
  self.timer -= 1
  self.label.configure(text="Score: "+str(self.score)+" Lives: "+str(self.lives)+" Time: "+str(self.timer))
  if(self.gameover == False):
   self.root.after(max(1, self.timerthreshold - self.speedup), self.update_clock)
 ### end of update_clock ###

 def key_event(self, event):
  direction = event.keysym
  if(direction in self.directions):
   try:
    self.q.put(direction, block=False)
   except:
    pass
 ### end of key_event ###

 def process_world(self):
  # acquire user input and process it if necessary
  if(self.q.qsize() > 0):
   self.move_frog(self.q.get())

  # update the state of non-frog objects
  self.update_world()

  # draw the world
  self.draw_world()

  # schedule another pass unless the game is over
  if(self.gameover == False):
   self.root.after(self.timerspeed, self.process_world)
  else:
   self.root.after(self.timerspeed, self.gameover_screen)
 ### end of process_world ###

 def move_frog(self, d):
  x = self.frogposition[0]
  y = self.frogposition[1]
  if(d == 'Up'):
   y -= 1
  elif(d == 'Down'):
   y += 1
  elif(d == 'Left'):
   x -= 1
  else:
   x += 1
  if(x >= 0 and y >= 0 and x < self.width and y < self.height):
   self.frogposition[0] = x
   self.frogposition[1] = y
   self.movedup = False
   if(d == 'Up' and y < self.highest):
    self.movedup = True
 ### end of move_frog ###

 def gameover_screen(self):
  self.label2 = tk.Label(text="Game over! Your score was: " + str(self.score))
  self.label2.pack()
 ### end of gameover_screen ###

 def update_world(self):
  # update the internal timer
  self.updateticks += 1

  # check for loss conditions
  if((self.timer == 0) or self.hit_by_car() == True or self.in_water() == True or self.home_twice() == True or self.in_grass() == True):
   self.process_death()
   return

  # credit good moves up
  if(self.movedup == True):
   self.score += self.pointsforup
   self.highest = self.frogposition[1]
   self.movedup = False

  # check for win condition
  if(self.at_home() == True):
   self.process_victory()
   return

  # check for total win
  if(self.all_done() == True):
   self.process_win()
   return

  # update the positions of the cars, logs, and turtles
  self.update_positions()
 ### end of update_world ###

 def all_done(self):
  if(len([x for x in self.homes if x[1]==False])==0):
   return True
  return False
 ### end of all_done ###

 def process_win(self):
  self.gameover = True
  return
 ### end of process_win ###

 def process_death(self):
  self.lives -= 1
  if(self.lives < 1):
   self.gameover = True
   return
  self.frogposition[0] = self.frogstart[0]
  self.frogposition[1] = self.frogstart[1]
  self.highest = 12
  self.timer = self.timerstart
 ### end of process_death ###

 def hit_by_car(self):
  for lane in self.lanes:
   if(lane.type != "car"):
    continue
   for car in lane.objects:
    if(car == self.frogposition):
     return True
  return False
 ### end of hit_by_car

 def in_water(self):
  if(self.frogposition[1] < self.waterbordertop or self.frogposition[1] > self.waterborderbottom):
   return False
  for lane in self.lanes:
   if(lane.type == "turtle"):
    for turtle in lane.objects:
     if(turtle == self.frogposition):
      return False
   elif(lane.type == "log"):
    for log in lane.objects:
     if(log == self.frogposition):
      return False
  return True
 ### end of in_water

 def home_twice(self):
  for h in self.homes:
   if(h[0] == self.frogposition and h[1] == True):
    return True
  return False
 ### end of home_twice

 def in_grass(self):
  if(self.frogposition[1] == 0 and self.at_home() == False):
   return True
  return False
 ### end of in_grass

 def at_home(self):
  for h in self.homes:
   if(h[0] == self.frogposition):
    return True
  return False
 ### end of at_home ###

 def process_victory(self):
  self.score += self.pointsforhome
  if(self.bugposition == self.frogposition):
   self.score += self.pointsforbug
  for h in self.homes:
   if (h[0] == self.frogposition):
    h[1] = True
    break
  self.timer = self.timerstart
  self.frogposition[0] = self.frogstart[0]
  self.frogposition[1] = self.frogstart[1]
  self.highest = 12
  self.speedup += self.speedchange
 ### end of process_victory ###

 def init_lanes(self):
  random.seed()
  self.lanes = []
  self.lanes.append(Lane(row=11, lanetype="car", maxnumber=10, replenish=0.1, direction=1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
  self.lanes.append(Lane(row=10, lanetype="car", maxnumber=8, replenish=0.2, direction=-1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
  self.lanes.append(Lane(row=9, lanetype="car", maxnumber=5, replenish=0.6, direction=1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
  self.lanes.append(Lane(row=8, lanetype="car", maxnumber=9, replenish=0.4, direction=-1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
  self.lanes.append(Lane(row=7, lanetype="car", maxnumber=6, replenish=0.3, direction=1, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
  self.lanes.append(Lane(row=5, lanetype="turtle", direction=-1, length=3, gap=4, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
  self.lanes.append(Lane(row=4, lanetype="log", direction=1, length=3, gap=3, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
  self.lanes.append(Lane(row=3, lanetype="log", direction=-1, length=8, gap=9, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
  self.lanes.append(Lane(row=2, lanetype="turtle", direction=1, length=2, gap=6, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
  self.lanes.append(Lane(row=1, lanetype="log", direction=-1, length=4, gap=4, width=self.width, speed=random.randint(self.minspeed, self.maxspeed)))
 ### end of init_lanes

 def init_special(self):
  self.bugposition = [2, 0]
  self.buglastupdate = 0
  self.bugspeed = random.randint(self.minbugspeed, self.maxbugspeed)
  self.homes = [[[2, 0], False], [[7, 0], False], [[12, 0], False], [[17, 0], False], [[22, 0], False]]
 ### end of init_special ###

 def update_positions(self):
  if(self.updateticks - self.buglastupdate >= self.bugspeed - self.speedup):
   self.buglastupdate = self.updateticks
   while(True):
    freeslots = [x for x in self.homes if x[1] == False]
    if(len(freeslots)==0):
     self.bugposition = [-1,-1]
     break
    if(len(freeslots)==1):
     self.bugposition = freeslots[0][0]
     break
    newhomeindex = random.randint(0, 4)
    if(self.homes[newhomeindex][0] != self.bugposition and self.homes[newhomeindex][1] == False):
     self.bugposition = self.homes[newhomeindex][0]
     break

  for lane in self.lanes:
   lanemovedfrog=False
   if(self.updateticks - lane.lanelastupdate >= lane.speed - self.speedup):
    lane.lanelastupdate = self.updateticks
   else:
    continue
   for o in lane.objects:
    if(o == self.frogposition and lanemovedfrog==False):
     self.move_frog(self.directions[int(0.5*lane.direction + 2.5)])
     lanemovedfrog=True
    o[0] += lane.direction
    if((o[0] < 0) or (o[0] >= self.width)):
     lane.objects.remove(o)
   if(lane.type == "car" and len(lane.objects) < lane.maxnumber and random.random() < lane.replenish):
    lane.objects.append([int((self.width-1)/2 - (self.width-1)*lane.direction/2), lane.row])
   if(lane.type == "log" or lane.type == "turtle"):
    if(lane.direction == 1):
     start = min([x[0] for x in lane.objects])
     nxt = min([x for x in range(start, self.width) if (len([y for y in lane.objects if y[0] == x]) == 0)])
     if(start >= lane.gap or (nxt - start) < lane.length):
      lane.objects.append([0, lane.row])
    else:
     start = max([x[0] for x in lane.objects])
     nxt = max([x for x in range(start, -1, -1) if (len([y for y in lane.objects if y[0] == x]) == 0)])
     if(self.width - start - 1 >= lane.gap or (start - nxt) < lane.length):
      lane.objects.append([self.width - 1, lane.row])
   lane.objects.sort()
 ### end of update_positions ###

 def draw_world(self):
  self.text.state = "normal"
  self.text.delete('1.0', str(self.width + 1) + '.' + '0')
  drawstr = ""
  # draw home row
  newstr = self.symbols["grass"] * self.width
  for h in self.homes:
   if(h[1] == False):
    if(self.bugposition == h[0]):
     newstr = self.str_replace(newstr, h[0][0], self.symbols["bug"])
    else:
     newstr = self.str_replace(newstr, h[0][0], self.symbols["freehome"])
   else:
    newstr = self.str_replace(newstr, h[0][0], self.symbols["fullhome"])
  drawstr += newstr
  drawstr += "\n"

  # draw water rows
  for index in range(self.waterborderbottom - self.waterbordertop + 1):
   newstr = self.symbols["water"] * self.width
   for lane in self.lanes:
    if(lane.row == index + self.waterbordertop):
     for o in lane.objects:
      if(lane.type == "log"):
       newstr = self.str_replace(newstr, o[0], self.symbols["log"])
      elif(lane.type == "turtle"):
       newstr = self.str_replace(newstr, o[0], self.symbols["turtle"])
   drawstr += newstr
   drawstr += "\n"

  # draw safe row
  drawstr += self.symbols["saferow"] * self.width
  drawstr += "\n"

  # draw car rows
  for index in range(len([l for l in self.lanes if l.type == "car"])):
   newstr = self.symbols["road"] * self.width
   for lane in self.lanes:
    if(lane.row == self.waterborderbottom + 2 +index):
     for o in lane.objects:
      if(lane.direction == 1):
       newstr = self.str_replace(newstr, o[0], self.symbols["rightcar"])
      elif(lane.direction == -1):
       newstr = self.str_replace(newstr, o[0], self.symbols["leftcar"])
   drawstr += newstr
   drawstr += "\n"

  # draw safe row
  drawstr += self.symbols["saferow"] * self.width

  # do actual drawing
  self.text.insert('1.0', drawstr)

  # draw frog
  self.text.delete(str(1 + self.frogposition[1]) + '.' + str(self.frogposition[0]))
  self.text.insert(str(1 + self.frogposition[1]) + '.' + str(self.frogposition[0]), self.symbols["frog"])

  # apply colors
  for sprite in self.sprites.keys():
   self.highlight_pattern(sprite, self.sprites[sprite])

  # turn off editability
  self.text.state = "disabled"
 ### end of draw_world ###

 def str_replace(self, targetstr, index, char):
  return targetstr[:index] + char + targetstr[index+1:]
 ### end of str_replace ###

 def highlight_pattern(self, sprite, tag):
  start = self.text.index("1.0")
  end = self.text.index("end")
  self.text.mark_set("matchStart", start)
  self.text.mark_set("matchEnd", start)
  self.text.mark_set("searchLimit", end)
  count = tk.IntVar()
  while True:
   index = self.text.search(sprite, "matchEnd", "searchLimit", count=count, regexp=False)
   if(index == ""):
    break
   self.text.mark_set("matchStart", index)
   self.text.mark_set("matchEnd", "%s+%sc" % (index, count.get()))
   self.text.tag_add(tag, "matchStart","matchEnd")
 ### end of highlight_pattern ###
### end of Frogger class ###

# Run the game!!!
frogger = Frogger()

2
Penso che il problema provenga dall'aggiornamento dello schermo. Se il programma funziona a 60 fps, sono necessari circa 16 ms. Ciò significa che il tuo ciclo principale non può essere eseguito ogni 1 ms. (Questa è la logica generale, ma non ho esperienza con Tkinter o altri sistemi di interfaccia grafica)
vedi il

Potrebbe valere la pena chiedere a SO di questo. Se lo fai, pubblica un link qui.

1
Ho preso il tuo consiglio e ho chiesto su SO: stackoverflow.com/questions/23999478/… La frequenza di aggiornamento dello schermo è impostata su ogni 20 tick di aggiornamento, che dovrebbe essere ogni 20ms o una velocità di 50fps. Sembra che dovrebbe essere banalmente facile per qualsiasi computer moderno.
RT,

2
Sulla base della risposta SO, ho modificato il programma per utilizzare un timer da 20 ms. Nel frattempo ho anche corretto alcuni altri bug. Se c'è abbastanza interesse, cercherò di aggiungere colori per rendere più facile vedere l'ASCII. Sentiti libero di commentare con suggerimenti, farò del mio meglio per implementarli.
RT,

Funziona davvero bene (assicurati di eseguire python3 filenamepiuttosto che python filename). Ti ho assegnato la generosità poiché l'altra risposta non è ancora finita

1

C ++ 1710

Ho avviato una versione della console ASCII. La rana può muoversi. Continuo a lavorare su altri requisiti. Non ho ancora effettuato il rilevamento o il punteggio degli oggetti. La rana si muove con i tasti w, a, s, d.

#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define P(x) cout<<x<<endl
#define R 13
#define C 25
string bank="=========================";
string water="~~~~~~~~~~~~~~~~~~~~~~~~~";
string road="-------------------------";
string log="LOG";
string car="CAR";
string frog="FROG";
string leaf="LEAF";
string rows[R];
bool gameover=false;
int frogX,frogY;

void insertObject(string obj, int row, int pos)
{
    string tmp=rows[row].erase(pos,obj.size());
    tmp.insert(pos,obj);
    rows[row]=tmp;
}

void newBoard()
{
int r,r2;
for(int i=0;i<R;i++)
{
    r=rand()%2+1;//1-3
    if(i==0||i==6||i==12)
    {
        rows[i]=bank;
    }
    else if(i>0&&i<6)
    {
        rows[i]=water;
        for(int j=0;j<r;j++)
        {
            r2=rand()%21;
            insertObject(log, i, r2);
        }
    }
    else
    {
        rows[i]=road;
        for(int j=0;j<r;j++)
        {
            r2=rand()%21;
            insertObject(car, i, r2);
        }
    }
}
insertObject(frog, 12, (int)(C-4)/2);
frogX=(int)(C-4)/2;
frogY=12;
insertObject(leaf, 0, (int)(C-4)/2);
}

void showBoard()
{
#ifdef WIN32
system("cls");
#else
system("clear");
#endif
for(int i=0;i<R;i++)
{
    P(rows[i]);
}
}

void playGame()
{
char c;
int i=0;
while(!gameover)
{
cin>>c;
switch(c)
{
case 'a':
    if(frogX!=0)frogX--;
    break;
case 'w':
    if(frogY!=0)frogY--;
    break;
case 'd':
    if(frogX<21)frogX++;
    break;
case 's':
    if(frogY!=12)frogY++;
    break;
default:
    break;
}
insertObject(frog, frogY, frogX);
showBoard();
i++;
if(i>12) gameover=true;
}
}

int main()
{
    srand(time(0));
    char play='y';
    while(play=='y')
    {
        newBoard();
        showBoard();
        playGame();
        P("Play Again (y/n)?");
        cin>>play;
    }

    return 0;
}

#define s stringper un po 'più di golf (nota: questo sembra essere un carattere più corto di typedef string s;) Oppure potresti farlo #define t typedef, quindi t string s;, anche se non so se funziona

inoltre potresti voler usare ++iinvece dii++
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.