Juego de Frogger-ish


13

¿Qué tal darle al renacido juego de arcade Frogger un nuevo estilo Code Golf!

Tu tarea es crear una versión de este juego clásico, con el menor número de caracteres posible. Use el idioma que prefiera ( se permiten bibliotecas, como jQuery , etc.).

Requisitos

  • Tienes 3 vidas y pierdes 1 vida de:
    • moviéndose fuera de la escena del juego.
    • ser atropellado por un vehículo.
    • saltando al agua.
    • saltando a una casa ya ocupada.
    • quedarse sin tiempo.
  • La rana se mueve con las teclas de flecha.
  • Hay un error de "teletransportación" con intervalos establecidos entre las cinco casas (los espacios entre la hierba en la parte superior).
  • Obtienes 10 puntos al avanzar un paso, 200 puntos de bonificación al atrapar un error y 500 puntos al llegar a una casa vacía.
  • Un temporizador marca más rápido cada nivel (los vehículos, las ranas y los troncos también deberían moverse más rápido en cada nivel).
  • Debe haber 5 carriles de vehículos y 3 carriles con troncos y 2 con tortugas.
  • Cada carril debe moverse a una velocidad elegida al azar (dentro de lo razonable).
  • Cuando una casa disponible se ocupa, aparece una rana en el punto de partida y usted controla esa desde ese punto.
  • Cuando las cinco casas han sido ocupadas, el temporizador se reinicia y las casas quedan vacías. Cuando finaliza el juego, se calculan y muestran los puntos de todos los niveles.

información adicional

La pantalla de inicio, la música y la tabla de puntuaciones no son necesarias. Tampoco necesita imitar el diseño al píxel. ¿Lo quieres en blanco y negro? ¿Lo quieres realmente minimalista? ¿O un cubo en lugar de una rana o un automóvil? ¡Funciona bien! Solo mantén el código estricto. ¡El código más corto gana!

ingrese la descripción de la imagen aquí


Comentarios purgados porque estaban obsoletos. Notifíqueme cualquier información perdida que pueda haber estado en comentarios eliminados.
Pomo de la puerta

Respuestas:


3

Python 3.3 - Sin golf

No he jugado a este golf en absoluto, ya que estaba más interesado en que un juego atractivo funcionara primero. En realidad, soy totalmente nuevo en Tk, por lo que si alguien tiene alguna sugerencia, realmente lo agradecería. Las velocidades ahora funcionan correctamente. Avíseme si desea ver características adicionales, por ejemplo, colores.

Código

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
Creo que el problema proviene de actualizar la pantalla. Si su programa se ejecuta a 60 fps, demora alrededor de 16 ms. Esto significa que su bucle principal no puede ejecutarse cada 1 ms. (Esta es la lógica general, pero no tengo experiencia con Tkinter u otros sistemas GUI)
consulte el

Podría valer la pena preguntar en SO sobre esto. Por favor, publique un enlace aquí si lo hace.

1
Seguí su consejo y pregunté sobre SO: stackoverflow.com/questions/23999478/… La frecuencia de actualización de la pantalla se establece en cada 20 ticks de actualización, que debería ser cada 20 ms, o una frecuencia de 50 fps. Parece que debería ser trivialmente fácil para cualquier computadora moderna.
RT

2
Basado en la respuesta SO, he cambiado el programa para usar un temporizador de 20 ms. Mientras tanto, también he solucionado algunos otros errores. Si hay suficiente interés, buscaré agregar colores para que el ASCII sea más fácil de ver. Siéntase libre de comentar con sugerencias, haré todo lo posible para implementarlas.
RT

Esto funciona muy bien (asegúrate de ejecutarlo en python3 filenamelugar de python filename). Le he otorgado la recompensa ya que la otra respuesta aún no ha terminado

1

C ++ 1710

Comencé una versión de consola ASCII. La rana puede moverse. Todavía trabajando en otros requisitos. Todavía no he realizado la detección o puntuación de objetos. La rana se mueve con las teclas 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 stringpor un poco más de golf (nota: esto parece ser un char más corto que typedef string s;) O podría hacerlo #define t typedef, entonces t string s;, aunque no sé si eso funciona

También es posible que desee utilizar en ++ilugar dei++
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.